Changeset 135


Ignore:
Timestamp:
01/16/09 07:00:07 (4 years ago)
Author:
jeroen
Message:

several bugfixes and the ability to restrict files from start to duration

Files:
3 added
45 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/as3/com/anttikupila/revolt/drawers/Line.as

    r123 r135  
    1414                override public function drawGFX(gfx:BitmapData, soundArray:Array):void { 
    1515                        lineSprite.graphics.clear(); 
    16                         lineSprite.graphics.moveTo(0, gfx.height/2);             
     16                        lineSprite.graphics.moveTo(0, gfx.height/2); 
    1717//                      lineSprite.graphics.beginFill(0x336600); 
    1818                        for (var i:uint = 0; i < soundArray.length; i+=2) { 
  • trunk/as3/com/anttikupila/revolt/presets/LineNoFourier.as

    r123 r135  
    11package 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.*; 
    36         
    4         public class LineNoFourier extends LineFourier { 
    5                 function LineNoFourier() { 
     7        public class LineNoFourier extends Preset { 
     8                function LineNoFourier(clr:String=undefined) { 
    69                        super(); 
    710                        fourier = false; 
     11                        drawers = new Array(new SimpleLine(clr)); 
     12                        effects = new Array(new Blur(),new Tint(0x000000,0.25)); 
     13                        scalers = new Array(); 
    814                } 
    915                 
    10                 override public function toString():String { 
    11                         return "Line without fourier transformation"; 
     16                public function toString():String { 
     17                        return "Line with fourier transformation"; 
    1218                } 
    1319        } 
  • trunk/as3/com/jeroenwijering/models/BasicModel.as

    r57 r135  
    11/** 
    2 * Wrapper for playback of progressively downloaded video. 
     2* This is the base model class all models must extent. 
    33**/ 
    44package com.jeroenwijering.models { 
    55 
    66 
    7 import flash.display.DisplayObject; 
     7import com.jeroenwijering.events.*; 
     8import com.jeroenwijering.player.Model; 
     9 
     10import flash.utils.clearInterval; 
     11import flash.utils.setInterval; 
    812 
    913 
    10 public interface ModelInterface { 
     14public class BasicModel { 
    1115 
    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 {}; 
    26103 
    27104 
  • trunk/as3/com/jeroenwijering/models/CameraModel.as

    r103 r135  
    11/** 
    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). 
    53**/ 
    64package com.jeroenwijering.models { 
     
    86 
    97import com.jeroenwijering.events.*; 
    10 import com.jeroenwijering.models.ModelInterface; 
     8import com.jeroenwijering.models.BasicModel; 
    119import com.jeroenwijering.player.Model; 
    12 import flash.events.*; 
     10 
    1311import flash.media.*; 
    14 import flash.net.*; 
    15 import flash.utils.clearInterval; 
    16 import flash.utils.setInterval; 
    1712 
    1813 
    19 public class CameraModel implements ModelInterface { 
     14public class CameraModel extends BasicModel { 
    2015 
    2116 
    22         /** reference to the model. **/ 
    23         private var model:Model; 
    2417        /** Camera object to be instantiated. **/ 
    2518        private var camera:Camera; 
     
    2821        /** Microphone object to be instantiated. **/ 
    2922        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; 
    3823 
    3924 
    4025        public function CameraModel(mod:Model):void { 
    41                 model = mod; 
     26                super(mod); 
    4227                try { 
    4328                        camera = Camera.getCamera(); 
     29                        camera.setMode(320,240,20); 
     30                        model.sendEvent(ModelEvent.META,{framerate:20,height:320,width:240}); 
    4431                        microphone = Microphone.getMicrophone(); 
    4532                        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) {} 
    5435        }; 
    5536 
    5637 
    57         /** Catch security errors. **/ 
    58         private function errorHandler(evt:ErrorEvent):void { 
    59                 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    60         }; 
    61  
    62  
    63  
    6438        /** 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(); 
    7044                } else {  
    71                         play(); 
     45                        stop(); 
     46                        model.sendEvent(ModelEvent.ERROR,{message:'No webcam found on this computer.'}); 
    7247                } 
    7348        }; 
     
    7550 
    7651        /** Pause playback. **/ 
    77         public function pause():void { 
     52        override public function pause():void { 
     53                super.pause(); 
    7854                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}); 
    8655        }; 
    8756 
    8857 
    8958        /** Resume playback **/ 
    90         public function play():void { 
     59        override public function play():void { 
     60                super.play(); 
    9161                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(); 
    12362        }; 
    12463 
    12564 
    12665        /** Destroy the videocamera. **/ 
    127         public function stop():void { 
    128                 position = 0; 
     66        override public function stop():void { 
    12967                video.attachCamera(null); 
    130                 clearInterval(interval); 
    131                 if(stream) { stream.publish(null); } 
     68                super.stop(); 
    13269        }; 
    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 {}; 
    15570 
    15671 
  • trunk/as3/com/jeroenwijering/models/HTTPModel.as

    r132 r135  
    11/** 
    2 * Wrapper for playback of http 'streaming' video. 
     2* Manages playback of http streaming flv. 
    33**/ 
    44package com.jeroenwijering.models { 
     
    66 
    77import com.jeroenwijering.events.*; 
    8 import com.jeroenwijering.models.ModelInterface; 
     8import com.jeroenwijering.models.BasicModel; 
    99import com.jeroenwijering.player.Model; 
    1010import com.jeroenwijering.utils.NetClient; 
     11 
    1112import flash.events.*; 
    12 import flash.display.DisplayObject; 
    13 import flash.media.SoundTransform; 
    14 import flash.media.Video; 
     13import flash.media.*; 
    1514import 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; 
     15import flash.utils.*; 
     16 
     17 
     18public 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; 
    2525        /** 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; 
    3127        /** Sound control object. **/ 
    32         private var transform:SoundTransform; 
    33         /** Interval ID for the time. **/ 
    34         private var timeinterval:Number; 
     28        protected var transform:SoundTransform; 
    3529        /** 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; 
    3733        /** 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; 
    4741 
    4842 
    4943        /** Constructor; sets up the connection and display. **/ 
    5044        public function HTTPModel(mod:Model):void { 
    51                 model = mod; 
     45                super(mod); 
    5246                connection = new NetConnection(); 
    53                 connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
    54                 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 
    55                 connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    5647                connection.connect(null); 
    5748                stream = new NetStream(connection); 
    5849                stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
    5950                stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
    60                 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,metaHandler); 
     51                stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    6152                stream.bufferTime = model.config['bufferlength']; 
    6253                stream.client = new NetClient(this); 
    6354                video = new Video(320,240); 
     55                video.smoothing = model.config['smoothing']; 
    6456                video.attachNetStream(stream); 
    6557                transform = new SoundTransform(); 
    66                 stream.soundTransform = transform; 
    6758                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; 
    7073        }; 
    7174 
    7275 
    7376        /** Catch security errors. **/ 
    74         private function errorHandler(evt:ErrorEvent):void { 
     77        protected function errorHandler(evt:ErrorEvent):void { 
     78                stop(); 
    7579                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    7680        }; 
     
    7882 
    7983        /** 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++) { 
    8389                        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                } 
    9298        }; 
    9399 
    94100 
    95101        /** Returns a key to add to the stream. **/ 
    96         private function getToken():String { 
     102        protected function getToken():String { 
    97103                return model.config['token']; 
    98104        }; 
    99105 
    100106 
     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 
    101125        /** 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                } 
    104131                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); 
    129135                clearInterval(loadinterval); 
    130136                loadinterval = setInterval(loadHandler,200); 
    131                 clearInterval(timeinterval); 
    132                 timeinterval = setInterval(timeHandler,100); 
    133                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    134137        }; 
    135138 
    136139 
    137140        /** Interval for the loading progress **/ 
    138         private function loadHandler():void { 
     141        protected function loadHandler():void { 
    139142                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}); 
    143151                        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                } 
    155155        }; 
    156156 
     
    158158        /** Get metadata information from netstream class. **/ 
    159159        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}); 
    169250                                } 
    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; 
    250259                } 
    251260        }; 
     
    253262 
    254263        /** Destroy the HTTP stream. **/ 
    255         public function stop():void { 
     264        override public function stop():void { 
     265                super.stop(); 
     266                stream.close(); 
    256267                clearInterval(loadinterval); 
    257                 clearInterval(timeinterval); 
    258                 offset = timeoffset = 0; 
    259                 h264 = false; 
     268                byteoffset = timeoffset = 0; 
    260269                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; 
    284271        }; 
    285272 
    286273 
    287274        /** Set the volume level. **/ 
    288         public function volume(vol:Number):void { 
     275        override public function volume(vol:Number):void { 
    289276                transform.volume = vol/100; 
    290277                stream.soundTransform = transform; 
  • trunk/as3/com/jeroenwijering/models/ImageModel.as

    r103 r135  
    11/** 
    2 * Wrapper for load and playback of images. 
     2* Model for playback of GIF/JPG/PNG images. 
    33**/ 
    44package com.jeroenwijering.models { 
     
    66 
    77import com.jeroenwijering.events.*; 
    8 import com.jeroenwijering.models.ModelInterface; 
     8import com.jeroenwijering.models.BasicModel; 
    99import com.jeroenwijering.player.Model; 
     10 
    1011import flash.display.Bitmap; 
    1112import flash.display.Loader; 
    1213import flash.events.*; 
    13 import flash.media.SoundMixer; 
    1414import flash.net.URLRequest; 
    15 import flash.utils.clearInterval; 
    16 import flash.utils.setInterval; 
     15import flash.system.LoaderContext; 
    1716 
    1817 
    19 public class ImageModel implements ModelInterface { 
     18public class ImageModel extends BasicModel { 
    2019 
    2120 
    22         /** reference to the model. **/ 
    23         private var model:Model; 
    24         /** Camera object to be instantiated. **/ 
     21        /** Loader that loads the image. **/ 
    2522        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; 
    3023 
    3124 
    3225        /** Constructor; sets up listeners **/ 
    3326        public function ImageModel(mod:Model):void { 
    34                 model = mod; 
     27                super(mod); 
    3528                loader = new Loader(); 
    3629                loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderHandler); 
     
    4134 
    4235        /** 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)); 
    4939        }; 
    5040 
     
    5242        /** Catch errors. **/ 
    5343        private function errorHandler(evt:ErrorEvent):void { 
     44                stop(); 
    5445                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    5546        }; 
     
    5950        private function loaderHandler(evt:Event):void { 
    6051                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}); 
    6256                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}); 
    8057        }; 
    8158 
     
    8865 
    8966 
    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  
    10667        /** 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) { 
    11170                        loader.close(); 
    112                 } else {  
     71                } else { 
    11372                        loader.unload(); 
    11473                } 
     74                super.stop(); 
    11575        }; 
    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 { }; 
    12776 
    12877 
  • trunk/as3/com/jeroenwijering/models/RTMPModel.as

    r119 r135  
    44* All playback functionalities are cross-server (FMS, Wowza, Red5), with the exception of: 
    55* - The SecureToken functionality (Wowza). 
    6 * - The FCSubscribe functionality (Limelight/Akamai FMS). 
    76* - getStreamLength / checkBandwidth (FMS3). 
    87**/ 
     
    1110 
    1211import com.jeroenwijering.events.*; 
    13 import com.jeroenwijering.models.ModelInterface; 
     12import com.jeroenwijering.models.BasicModel; 
    1413import com.jeroenwijering.player.Model; 
    1514import com.jeroenwijering.utils.NetClient; 
    1615import com.jeroenwijering.utils.TEA; 
    1716 
    18 import flash.display.DisplayObject; 
    1917import flash.events.*; 
    2018import flash.media.*; 
     
    2321 
    2422 
    25 public class RTMPModel implements ModelInterface { 
    26  
    27  
    28         /** reference to the model. **/ 
    29         private var model:Model; 
     23public class RTMPModel extends BasicModel { 
     24 
     25 
    3026        /** Video object to be instantiated. **/ 
    31         private var video:Video; 
     27        protected var video:Video; 
    3228        /** NetConnection object for setup of the video stream. **/ 
    33         private var connection:NetConnection; 
     29        protected var connection:NetConnection; 
    3430        /** NetStream instance that handles the stream IO. **/ 
    35         private var stream:NetStream; 
     31        protected var stream:NetStream; 
    3632        /** 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; 
    4434 
    4535 
    4636        /** Constructor; sets up the connection and display. **/ 
    4737        public function RTMPModel(mod:Model):void { 
    48                 model = mod; 
     38                super(mod); 
    4939                connection = new NetConnection(); 
    5040                connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
    5141                connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 
    5242                connection.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
    53                 connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,metaHandler); 
     43                connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    5444                connection.objectEncoding = ObjectEncoding.AMF0; 
    5545                connection.client = new NetClient(this); 
    5646                video = new Video(320,240); 
    57                 quality(model.config['quality']); 
     47                video.smoothing = model.config['smoothing']; 
    5848                transform = new SoundTransform(); 
    59                 model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    6049        }; 
    6150 
    6251 
    6352        /** Catch security errors. **/ 
    64         private function errorHandler(evt:ErrorEvent):void { 
     53        protected function errorHandler(evt:ErrorEvent):void { 
     54                stop(); 
    6555                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    6656        }; 
     
    8373 
    8474        /** Load content. **/ 
    85         public function load():void { 
    86                 video.clear(); 
     75        override public function load(itm:Object):void { 
     76                super.load(itm); 
    8777                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']); 
    9679        }; 
    9780 
     
    9982        /** Get metadata information from netstream class. **/ 
    10083        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}); 
    105121                        } 
    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(); 
    112129                        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); 
    164137                stream.seek(pos); 
    165138        }; 
    166139 
    167140 
    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() { 
    171143                stream = new NetStream(connection); 
    172144                stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
    173145                stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
    174                 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,metaHandler); 
     146                stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    175147                stream.bufferTime = model.config['bufferlength']; 
    176148                stream.client = new NetClient(this); 
    177149                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']); 
    185153        }; 
    186154 
    187155 
    188156        /** Receive NetStream status updates. **/ 
    189         private function statusHandler(evt:NetStatusEvent):void { 
    190                 switch (evt.info.code) {  
     157        protected function statusHandler(evt:NetStatusEvent):void { 
     158                switch (evt.info.code) { 
    191159                        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); 
    192164                                if(evt.info.secureToken != undefined) { 
    193165                                        connection.call("secureTokenResponse",null,TEA.decrypt(evt.info.secureToken,model.config['token'])); 
    194166                                } 
    195                                 if(model.config['subscribe']) { 
    196                                         timeout = setInterval(subscribe,2000,getID(model.playlist[model.config['item']]['file'])); 
    197                                 } else { 
    198                                         setStream(); 
    199                                 } 
    200167                                break; 
    201168                        case  'NetStream.Seek.Notify': 
    202                                 clearInterval(timeinterval); 
    203                                 timeinterval = setInterval(timeHandler,100); 
     169                                clearInterval(interval); 
     170                                interval = setInterval(positionInterval,100); 
    204171                                break; 
    205172                        case 'NetConnection.Connect.Rejected': 
    206173                                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']); 
    210176                                } 
     177                                break; 
     178                        case 'NetStream.Failed': 
     179                                model.sendEvent(ModelEvent.META,{info:evt.info.code}); 
    211180                        case 'NetStream.Play.StreamNotFound': 
     181                                stop(); 
     182                                model.sendEvent(ModelEvent.ERROR,{message:"Stream not found: "+item['file']}); 
     183                                break; 
    212184                        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']}); 
    214187                                break; 
    215188                        default: 
     
    221194 
    222195        /** Destroy the stream. **/ 
    223         public function stop():void { 
    224                 clearInterval(timeinterval); 
     196        override public function stop():void { 
     197                if(stream) {  
     198                        stream.close(); 
     199                } 
    225200                connection.close(); 
    226                 if(stream) { stream.close(); } 
    227                 video.attachNetStream(null); 
     201                super.stop(); 
    228202        }; 
    229203 
     
    231205        /** Get the streamlength returned from the connection. **/ 
    232206        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']}); 
    258208        }; 
    259209 
    260210 
    261211        /** Set the volume level. **/ 
    262         public function volume(vol:Number):void { 
     212        override public function volume(vol:Number):void { 
    263213                transform.volume = vol/100; 
    264214                if(stream) {  
  • trunk/as3/com/jeroenwijering/models/SoundModel.as

    r103 r135  
    66 
    77import com.jeroenwijering.events.*; 
    8 import com.jeroenwijering.models.ModelInterface; 
     8import com.jeroenwijering.models.BasicModel; 
    99import com.jeroenwijering.player.Model; 
     10 
    1011import flash.events.*; 
    1112import flash.media.*; 
    1213import flash.net.URLRequest; 
    1314import flash.utils.clearInterval; 
    14 import flash.utils.setInterval; 
    1515 
    1616 
    17 public class SoundModel implements ModelInterface { 
     17public class SoundModel extends BasicModel { 
    1818 
    1919 
    20         /** reference to the model. **/ 
    21         private var model:Model; 
    2220        /** sound object to be instantiated. **/ 
    2321        private var sound:Sound; 
     
    2826        /** Sound context object. **/ 
    2927        private var context:SoundLoaderContext; 
    30         /** Interval ID for the time. **/ 
    31         private var interval:Number; 
    32         /** Current position. **/ 
    33         private var position:Number; 
    3428 
    3529 
    3630        /** Constructor; sets up the connection and display. **/ 
    3731        public function SoundModel(mod:Model):void { 
    38                 model = mod; 
     32                super(mod); 
    3933                transform = new SoundTransform(); 
     34                context = new SoundLoaderContext(model.config['bufferlength']*1000,true); 
    4035                model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    41                 context = new SoundLoaderContext(model.config['bufferlength']*1000,true); 
    4236        }; 
    4337 
     
    5246        /** Catch errors. **/ 
    5347        private function errorHandler(evt:ErrorEvent):void { 
     48                stop(); 
    5449                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    55                 stop(); 
    5650        }; 
    5751 
     
    6155                try { 
    6256                        var id3:ID3Info = sound.id3; 
    63                         var obj = { 
     57                        var obj:Object = { 
    6458                                type:'id3', 
    6559                                album:id3.album, 
     
    6761                                comment:id3.comment, 
    6862                                genre:id3.genre, 
    69                                 songName:id3.songName, 
     63                                name:id3.songName, 
    7064                                track:id3.track, 
    7165                                year:id3.year 
     
    7771 
    7872        /** 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); 
    8175                sound = new Sound(); 
    8276                sound.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
     
    8478                sound.addEventListener(Event.COMPLETE,loadedHandler); 
    8579                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); 
    8781                play(); 
    8882        }; 
     
    9185        /** Sound has been loaded, so the final duration is known. **/ 
    9286        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']}); 
    9488        }; 
    9589 
    9690 
    9791        /** Pause the sound. **/ 
    98         public function pause():void { 
    99                 clearInterval(interval); 
     92        override public function pause():void { 
     93                super.pause(); 
    10094                channel.stop(); 
    101                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 
    10295        }; 
    10396 
    10497 
    10598        /** Play the sound. **/ 
    106         public function play():void { 
     99        override public function play():void { 
     100                super.play(); 
    107101                channel = sound.play(position*1000,0,transform); 
    108                 channel.removeEventListener(Event.SOUND_COMPLETE,completeHandler); 
    109102                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                } 
    112125        }; 
    113126 
     
    121134 
    122135 
    123         /** Change quality setting. **/ 
    124         public function quality(typ:Boolean):void {}; 
    125  
    126  
    127136        /** 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 { 
    131138                channel.stop(); 
    132                 play(); 
     139                super.seek(pos); 
    133140        }; 
    134141 
    135142 
    136143        /** Destroy the sound. **/ 
    137         public function stop():void { 
    138                 clearInterval(interval); 
     144        override public function stop():void { 
    139145                if(channel) { channel.stop(); } 
    140146                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(); 
    158148        }; 
    159149 
    160150 
    161151        /** Set the volume level. **/ 
    162         public function volume(vol:Number):void { 
     152        override public function volume(vol:Number):void { 
    163153                transform.volume = vol/100; 
    164154                if(channel) { 
  • trunk/as3/com/jeroenwijering/models/VideoModel.as

    r104 r135  
    66 
    77import com.jeroenwijering.events.*; 
    8 import com.jeroenwijering.models.ModelInterface; 
     8import com.jeroenwijering.models.BasicModel; 
    99import com.jeroenwijering.player.Model; 
    1010import com.jeroenwijering.utils.NetClient; 
     11 
    1112import flash.events.*; 
    12 import flash.display.DisplayObject; 
    13 import flash.media.SoundTransform; 
    14 import flash.media.Video; 
     13import flash.media.*; 
    1514import flash.net.*; 
    16 import flash.utils.clearInterval; 
    17 import flash.utils.setInterval; 
     15import flash.utils.*; 
    1816 
    1917 
    20 public class VideoModel implements ModelInterface { 
     18public class VideoModel extends BasicModel { 
    2119 
    2220 
    23         /** reference to the model. **/ 
    24         private var model:Model; 
    2521        /** Video object to be instantiated. **/ 
    26         private var video:Video; 
     22        protected var video:Video; 
    2723        /** NetConnection object for setup of the video stream. **/ 
    28         private var connection:NetConnection; 
     24        protected var connection:NetConnection; 
    2925        /** NetStream instance that handles the stream IO. **/ 
    30         private var stream:NetStream; 
     26        protected var stream:NetStream; 
    3127        /** Sound control object. **/ 
    32         private var transform:SoundTransform; 
    33         /** Interval ID for the time. **/ 
    34         private var timeinterval:Number; 
     28        protected var transform:SoundTransform; 
    3529        /** Interval ID for the loading. **/ 
    36         private var loadinterval:Number; 
    37         /** Metadata received switch. **/ 
    38         private var metadata:Boolean; 
     30        protected var loadinterval:Number; 
    3931 
    4032 
    4133        /** Constructor; sets up the connection and display. **/ 
    4234        public function VideoModel(mod:Model):void { 
    43                 model = mod; 
     35                super(mod); 
    4436                connection = new NetConnection(); 
    45                 connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
    46                 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 
    47                 connection.objectEncoding = ObjectEncoding.AMF0; 
    4837                connection.connect(null); 
    4938                stream = new NetStream(connection); 
    5039                stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
    5140                stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
    52                 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,metaHandler); 
     41                stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    5342                stream.bufferTime = model.config['bufferlength']; 
    5443                stream.client = new NetClient(this); 
    5544                video = new Video(320,240); 
     45                video.smoothing = model.config['smoothing']; 
    5646                video.attachNetStream(stream); 
    5747                transform = new SoundTransform(); 
    58                 stream.soundTransform = transform; 
    59                 quality(model.config['quality']); 
    6048                model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    6149        }; 
     
    6351 
    6452        /** Catch security errors. **/ 
    65         private function errorHandler(evt:ErrorEvent):void { 
     53        protected function errorHandler(evt:ErrorEvent):void { 
     54                stop(); 
    6655                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    6756        }; 
     
    6958 
    7059        /** Load content. **/ 
    71         public function load():void { 
    72                 video.clear(); 
     60        override public function load(itm:Object):void { 
     61                super.load(itm); 
    7362                model.mediaHandler(video); 
    74                 stream.play(model.playlist[model.config['item']]['file']); 
     63                stream.play(item['file']); 
     64                interval = setInterval(positionInterval,100); 
    7565                loadinterval = setInterval(loadHandler,200); 
    76                 timeinterval = setInterval(timeHandler,100); 
    77                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    7866        }; 
    7967 
    8068 
    8169        /** Interval for the loading progress **/ 
    82         private 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; 
    8573                model.sendEvent(ModelEvent.LOADED,{loaded:ldd,total:ttl}); 
    8674                if(ldd == ttl && ldd > 0) { 
     
    9078 
    9179 
    92         /** Catch noncritical errors. **/ 
    93         private function metaHandler(evt:ErrorEvent):void { 
    94                 model.sendEvent(ModelEvent.META,{error:evt.text}); 
    95         }; 
    96  
    97  
    9880        /** Get metadata information from netstream class. **/ 
    9981        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']; 
    10988                } 
    11089                model.sendEvent(ModelEvent.META,dat); 
     
    11392 
    11493        /** Pause playback. **/ 
    115         public function pause():void { 
    116                 clearInterval(timeinterval); 
     94        override public function pause():void { 
     95                super.pause(); 
    11796                stream.pause(); 
    118                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 
    11997        }; 
    12098 
    12199 
    122100        /** Resume playing. **/ 
    123         public function play():void { 
     101        override public function play():void { 
     102                super.play(); 
    124103                stream.resume(); 
    125                 timeinterval = setInterval(timeHandler,100); 
    126                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
    127104        }; 
    128105 
    129106 
    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}); 
    138125                } 
    139126        }; 
    140127 
    141128 
    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); 
    147133        }; 
    148134 
    149135 
    150136        /** 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; 
    158150                } 
    159                 model.sendEvent(ModelEvent.META,{info:evt.info.code}); 
    160151        }; 
    161152 
    162153 
    163154        /** 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(); 
    170157                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(); 
    189159        }; 
    190160 
    191161 
    192162        /** Set the volume level. **/ 
    193         public function volume(vol:Number):void { 
     163        override public function volume(vol:Number):void { 
    194164                transform.volume = vol/100; 
    195165                stream.soundTransform = transform; 
  • trunk/as3/com/jeroenwijering/models/YoutubeModel.as

    r115 r135  
    11/** 
    2 * Wrapper for load and playback of Youtube videos. 
     2* Wrapper for load and playback of Youtube videos through their API. 
    33**/ 
    44package com.jeroenwijering.models { 
     
    66 
    77import com.jeroenwijering.events.*; 
    8 import com.jeroenwijering.models.ModelInterface; 
     8import com.jeroenwijering.models.BasicModel; 
    99import com.jeroenwijering.player.Model; 
    10 import flash.display.Sprite; 
     10 
    1111import flash.display.Loader; 
    12 import flash.net.URLRequest; 
    1312import flash.events.*; 
    1413import 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; 
     14import flash.net.URLRequest; 
     15import flash.system.Security; 
     16 
     17 
     18public class YoutubeModel extends BasicModel { 
     19 
     20 
    2521        /** Loader for loading the YouTube proxy **/ 
    2622        private var loader:Loader; 
     
    4137        /** Setup YouTube connections and load proxy. **/ 
    4238        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                } 
    4550                outgoing = new LocalConnection(); 
    4651                outgoing.allowDomain('*'); 
     
    5661                loader = new Loader(); 
    5762                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; 
    6063                loader.load(new URLRequest(ytb)); 
    6164        }; 
     
    6467        /** Catch load errors. **/ 
    6568        private function errorHandler(evt:ErrorEvent):void { 
     69                stop(); 
    6670                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
    6771        }; 
     
    8690 
    8791        /** Load the YouTube movie. **/ 
    88         public function load():void { 
     92        override public function load(itm:Object):void { 
     93                super.load(itm); 
    8994                if(connected) { 
    9095                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    9196                        loading = true; 
    9297                        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); 
    96100                                model.mediaHandler(loader); 
    97101                        } 
     
    101105 
    102106        /** Pause the YouTube movie. **/ 
    103         public function pause():void { 
     107        override public function pause():void { 
    104108                outgoing.send('AS3_'+unique,"pauseVideo"); 
    105109        }; 
     
    108112 
    109113        /** Play or pause the video. **/ 
    110         public function play():void { 
     114        override public function play():void { 
    111115                outgoing.send('AS3_'+unique,"playVideo"); 
    112116        }; 
     
    117121                outgoing.send('AS3_'+unique,"setSize",320,240); 
    118122                model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    119                 if(loading) { load(); } 
     123                if(loading) { load(item); } 
    120124        }; 
    121125 
     
    129133        /** Catch youtube errors. **/ 
    130134        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']}); 
    133136                stop(); 
    134137        }; 
     
    168171        /** Catch Youtube position changes **/ 
    169172        public function onTimeChange(pos:Number,dur:Number):void { 
    170                 model.sendEvent(ModelEvent.TIME,{position:pos}); 
     173                model.sendEvent(ModelEvent.TIME,{position:pos,duration:dur}); 
    171174                if(!metasent) { 
    172175                        model.sendEvent(ModelEvent.META,{width:320,height:240,duration:dur}); 
     
    176179 
    177180 
    178         /** Toggle quality (perhaps access the H264 versions later?). **/ 
    179         public function quality(stt:Boolean):void {}; 
    180  
    181  
    182181        /** Seek to position. **/ 
    183         public function seek(pos:Number):void { 
     182        override public function seek(pos:Number):void { 
    184183                outgoing.send('AS3_'+unique,"seekTo",pos); 
    185184                play(); 
     
    188187 
    189188        /** Destroy the youtube video. **/ 
    190         public function stop():void { 
     189        override public function stop():void { 
    191190                metasent = false; 
    192191                outgoing.send('AS3_'+unique,"stopVideo"); 
     192                super.stop(); 
    193193        }; 
    194194 
     
    196196 
    197197        /** Set the volume level. **/ 
    198         public function volume(pct:Number):void { 
     198        override public function volume(pct:Number):void { 
    199199                outgoing.send('AS3_'+unique,"setVolume",pct); 
    200200        }; 
  • trunk/as3/com/jeroenwijering/parsers/ATOMParser.as

    r123 r135  
    4343                                        } else if (i.@rel == 'enclosure') { 
    4444                                                itm['file'] = i.@href.toString(); 
    45                                                 if(i.@type) { 
    46                                                         itm['type'] = ObjectParser.MIMETYPES[i.@type.toString()]; 
    47                                                 } 
    4845                                        } 
    4946                                        break; 
  • trunk/as3/com/jeroenwijering/parsers/MediaParser.as

    r103 r135  
    2121        * @see                  RSSParser 
    2222        **/ 
    23         public static function parseGroup(obj:XML,itm:Object):Object {  
     23        public static function parseGroup(obj:XML,itm:Object):Object { 
    2424                for each (var i:XML in obj.children()) { 
    2525                        switch(i.localName()) { 
    2626                                case 'content': 
    27                                         if(!itm['file']) { 
     27                                if( !itm['file']) { 
    2828                                                itm['file'] = i.@url.toString(); 
    2929                                        } 
    30                                         if(i.@type) { 
    31                                                 itm['type'] = ObjectParser.MIMETYPES[i.@type.toString()]; 
     30                                        if(i.@start) { 
     31                                                itm['start'] = Strings.seconds(i.@start.toString()); 
    3232                                        } 
    3333                                        if(i.@duration) { 
    3434                                                itm['duration'] = Strings.seconds(i.@duration.toString()); 
    35                                         } 
    36                                         if(i.@start) { 
    37                                                 itm['start'] = Strings.seconds(i.@start.toString()); 
    3835                                        } 
    3936                                        if(i.children().length() >0) { 
  • trunk/as3/com/jeroenwijering/parsers/ObjectParser.as

    r103 r135  
    2020                'image':undefined, 
    2121                'link':undefined, 
    22                 'title':undefined, 
    2322                'start':0, 
    2423                'streamer':undefined, 
    2524                'tags':undefined, 
     25                'title':undefined, 
    2626                'type':undefined 
    2727        }; 
     
    4848                'vp6':'video' 
    4949        }; 
    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         }; 
    7450 
    7551 
  • trunk/as3/com/jeroenwijering/parsers/RSSParser.as

    r100 r135  
    3939                                case 'enclosure': 
    4040                                        itm['file'] = i.@url.toString(); 
    41                                         itm['type'] = ObjectParser.MIMETYPES[i.@type.toString()]; 
    4241                                        break; 
    4342                                case 'title': 
  • trunk/as3/com/jeroenwijering/parsers/SMILParser.as

    r100 r135  
    8585                                        itm['file'] = obj.@src.toString(); 
    8686                                        break; 
    87                                 case 'type': 
    88                                         itm['type'] = ObjectParser.MIMETYPES[obj.@type.toString()]; 
    89                                         break; 
    9087                                case 'dur': 
    9188                                        itm['duration'] = Strings.seconds(obj.@dur.toString()); 
  • trunk/as3/com/jeroenwijering/player/Controller.as

    r124 r135  
    6666                view.addEventListener(ViewEvent.PLAY,playHandler); 
    6767                view.addEventListener(ViewEvent.PREV,prevHandler); 
    68                 view.addEventListener(ViewEvent.QUALITY,qualityHandler); 
    6968                view.addEventListener(ViewEvent.REDRAW,redrawHandler); 
    7069                view.addEventListener(ViewEvent.SEEK,seekHandler); 
     
    108107        /** Return the type of specific playlistitem (the Model to play it with) **/ 
    109108        private function getModelType(itm:Object):String { 
    110                 // no file, so nothing to play 
    111109                if(!itm['file']) { 
    112110                        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']) { 
    123114                        if(itm['streamer'].substr(0,4) == 'rtmp') { 
    124115                                return 'rtmp'; 
     116                        } else if(itm['streamer'].substr(0,4) == 'http') { 
     117                                return 'http'; 
    125118                        } 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                } 
    139126        }; 
    140127 
     
    199186                        var fmt:String = dat.localName().toLowerCase(); 
    200187                } 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.'})); 
    202189                        return; 
    203190                } 
     
    219206                                break; 
    220207                        default: 
    221                                 dispatchEvent(new ControllerEvent(ControllerEvent.ERROR,'Unknown playlist format: '+fmt)); 
     208                                dispatchEvent(new ControllerEvent(ControllerEvent.ERROR,{message:'Unknown playlist format: '+fmt})); 
    222209                                return; 
    223210                } 
     
    227214        /** Update playlist item duration. **/ 
    228215        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) { 
    230217                        playlist[config['item']]['duration'] = evt.data.duration; 
    231218                } 
     
    271258                                dispatchEvent(new ControllerEvent(ControllerEvent.PLAY,{state:true})); 
    272259                        } 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})); 
    274261                        } else if(evt.data.state != false && config['state'] == ModelStates.IDLE) { 
    275262                                playItem(); 
     
    284271        /** Direct the model to play a new item. **/ 
    285272        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)) { 
    290274                        config['item'] = nbr; 
    291275                } 
     
    297281        private function playlistHandler(ply:Array):void { 
    298282                for(var i:Number=ply.length-1; i>-1; i--) { 
    299                         if(!ply[i]['streamer']) { ply[i]['streamer'] = config['streamer']; } 
    300283                        if(!ply[i]['duration']) { ply[i]['duration'] = 0; } 
    301284                        if(!ply[i]['start']) { ply[i]['start'] = 0; } 
     285                        if(!ply[i]['streamer']) { ply[i]['streamer'] = config['streamer']; } 
    302286                        ply[i]['type'] = getModelType(ply[i]); 
    303287                        if(!ply[i]['type']) { ply.splice(i,1); } 
     
    329313                        playItem(config['item']-1); 
    330314                } 
    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']})); 
    347315        }; 
    348316 
  • trunk/as3/com/jeroenwijering/player/Model.as

    r125 r135  
    11/** 
    2 * Wrap all media API's and manage playback. 
     2* Wraps all media APIs (all models) and manages thumbnail display. 
    33**/ 
    44package com.jeroenwijering.player { 
     
    99import com.jeroenwijering.player.*; 
    1010import com.jeroenwijering.utils.*; 
     11 
    1112import flash.display.*; 
    12 import flash.events.Event; 
    13 import flash.events.EventDispatcher; 
     13import flash.events.*; 
    1414import flash.net.URLRequest; 
    1515import flash.system.LoaderContext; 
    16 import flash.utils.getDefinitionByName; 
    1716 
    1817 
     
    3231        /** Loader for the preview image. **/ 
    3332        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. **/ 
    3536        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. **/ 
    4140        public function Model(cfg:Object,skn:MovieClip,ldr:SPLoader,ctr:Controller):void { 
    4241                config = cfg; 
    4342                skin = skn; 
    4443                sploader = ldr; 
    45                 Draw.clear(skin.display.media); 
    4644                controller = ctr; 
    4745                controller.addEventListener(ControllerEvent.ITEM,itemHandler); 
     
    4947                controller.addEventListener(ControllerEvent.PLAY,playHandler); 
    5048                controller.addEventListener(ControllerEvent.PLAYLIST,playlistHandler); 
    51                 controller.addEventListener(ControllerEvent.QUALITY,qualityHandler); 
    5249                controller.addEventListener(ControllerEvent.RESIZE,resizeHandler); 
    5350                controller.addEventListener(ControllerEvent.SEEK,seekHandler); 
     
    5552                controller.addEventListener(ControllerEvent.VOLUME,volumeHandler); 
    5653                thumb = new Loader(); 
    57                 thumb.contentLoaderInfo.addEventListener(Event.COMPLETE,resizeHandler); 
     54                thumb.contentLoaderInfo.addEventListener(Event.COMPLETE,thumbHandler); 
     55                Draw.clear(skin.display.media); 
    5856                skin.display.addChildAt(thumb,skin.display.getChildIndex(skin.display.media)+1); 
     57                skin.display.media.visible = false; 
    5958                models = new Object(); 
    6059        }; 
    6160 
    6261 
    63         /** Item change: switch the curently active model if there's a new URL **/ 
     62        /** Item change: stop the old model and start the new one. **/ 
    6463        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); 
    7573                } 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                } 
    7980        }; 
    8081 
     
    9293                                models[typ] = new ImageModel(this); 
    9394                                break; 
     95                        case 'lighttpd': 
     96                                models[typ] = new LighttpdModel(this); 
     97                                break; 
     98                        case 'nginx': 
     99                                models[typ] = new NginxModel(this); 
     100                                break; 
    94101                        case 'rtmp': 
    95102                                models[typ] = new RTMPModel(this); 
     
    108115 
    109116 
    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 { 
    112123                Draw.clear(skin.display.media); 
    113                 skin.display.media.addChild(chd); 
     124                skin.display.media.addChild(obj); 
    114125                resizeHandler(); 
    115126        }; 
    116127 
    117128 
    118         /** Load the configuration array. **/ 
     129        /** Make the current model toggle its mute state. **/ 
    119130        private function muteHandler(evt:ControllerEvent):void { 
    120                 if(currentModel) { 
     131                if(item) { 
    121132                        if(evt.data.state == true) { 
    122                                 models[currentModel].volume(0); 
     133                                models[item['type']].volume(0); 
    123134                        } else { 
    124                                 models[currentModel].volume(config['volume']); 
     135                                models[item['type']].volume(config['volume']); 
    125136                        } 
    126137                } 
     
    128139 
    129140 
    130         /** Togge the playback state. **/ 
     141        /** Make the current model play or pause. **/ 
    131142        private function playHandler(evt:ControllerEvent):void { 
    132                 if(currentModel) { 
     143                if(item) { 
    133144                        if(evt.data.state == true) { 
    134                                 models[currentModel].play(); 
     145                                models[item['type']].play(); 
    135146                        } else {  
    136                                 models[currentModel].pause(); 
     147                                models[item['type']].pause(); 
    137148                        } 
    138149                } 
     
    140151 
    141152 
    142         /** Send an idle with new playlist. **/ 
     153        /** Load a new thumbnail. **/ 
    143154        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)); 
    152159                } 
    153160        }; 
     
    158165                var cfg:Object = sploader.getPluginConfig(sploader.getPlugin('display')); 
    159166                Stretcher.stretch(skin.display.media,cfg['width'],cfg['height'],config['stretching']); 
    160                 if(thumb.content) { 
     167                if(thumb.width > 10) { 
    161168                        Stretcher.stretch(thumb,cfg['width'],cfg['height'],config['stretching']); 
    162169                } 
     
    164171 
    165172 
    166         /** Seek inside a file. **/ 
     173        /** Make the current model seek. **/ 
    167174        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. **/ 
    175182        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        **/ 
    185197        public function sendEvent(typ:String,dat:Object):void { 
    186198                switch(typ) {  
     
    191203                                switch(dat['newstate']) { 
    192204                                        case ModelStates.IDLE: 
     205                                                sendEvent(ModelEvent.LOADED,{loaded:0,offset:0,total:0}); 
    193206                                        case ModelStates.COMPLETED: 
    194207                                                thumb.visible = true; 
    195208                                                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']}); 
    199210                                                break; 
    200211                                        case ModelStates.PLAYING: 
    201                                                 var ext:String = playlist[config['item']]['file'].substr(-3).toLowerCase(); 
     212                                                var ext:String = item['file'].substr(-3).toLowerCase(); 
    202213                                                if(ext != 'aac' && ext != 'mp3' && ext != 'm4a') { 
    203214                                                        thumb.visible = false; 
     
    210221                                } 
    211222                                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; 
    227223                        case ModelEvent.META: 
    228224                                if(dat.width) { resizeHandler(); } 
     
    234230 
    235231 
    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. **/ 
    247242        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                } 
    257246        }; 
    258247 
  • trunk/as3/com/jeroenwijering/player/Player.as

    r132 r135  
    1919        public var config:Object = { 
    2020                author:undefined, 
    21                 description:undefined,  
     21                description:undefined, 
    2222                date:undefined, 
    2323                duration:0, 
     
    5050                logo:undefined, 
    5151                mute:false, 
    52                 quality:true, 
    5352                repeat:'none', 
    5453                resizing:true, 
    5554                shuffle:false, 
     55                smoothing:true, 
    5656                state:'IDLE', 
    5757                stretching:'uniform', 
    5858                volume:90, 
    59                  
     59 
    6060                abouttext:undefined, 
    6161                aboutlink:"http://www.longtailvideo.com/players/jw-flv-player/", 
     
    6767                token:undefined, 
    6868                tracecall:undefined, 
    69                 version:'4.3.132' 
     69                version:'4.4.135' 
    7070        }; 
    7171        /** 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/'; 
    7373        /** Reference to all stage graphics. **/ 
    7474        public var skin:MovieClip; 
  • trunk/as3/com/jeroenwijering/player/SPLoader.as

    r129 r135  
    4141 
    4242        /** 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 { 
    4444                var obj:Object = {reference:pgi,name:nam,position:'over',size:180,x:0,y:0,width:400,height:300}; 
    4545                // hack for the playlist/controlbar flashvars 
     
    5353                        obj['size'] = player.config['playlistsize']; 
    5454                } 
     55                try { 
     56                        for(var org:String in pgi.config) { 
     57                                obj[org] = pgi.config[org]; 
     58                        } 
     59                } catch (err:Error) {} 
    5560                for(var str:String in player.config) { 
    5661                        if (str.indexOf(nam + ".") == 0) { 
     
    5863                        } 
    5964                } 
     65                try { pgi.config = obj; } catch (err:Error) {} 
    6066                plugins.push(obj); 
    6167                pgi.initializePlugin(player.view); 
  • trunk/as3/com/jeroenwijering/player/View.as

    r132 r135  
    66 
    77import com.jeroenwijering.events.*; 
    8 import com.jeroenwijering.utils.Debug; 
    9 import com.jeroenwijering.utils.Strings; 
     8import com.jeroenwijering.utils.*; 
    109 
    1110import flash.display.MovieClip; 
     
    143142 
    144143 
    145         private function getPlaylist():Array {  
    146                 return controller.playlist;  
     144        private function getPlaylist():Array { 
     145                return controller.playlist; 
    147146        }; 
    148147 
     
    260259                addControllerListener(ControllerEvent.PLAY,setController); 
    261260                addControllerListener(ControllerEvent.PLAYLIST,setController); 
    262                 addControllerListener(ControllerEvent.QUALITY,setController); 
    263261                addControllerListener(ControllerEvent.RESIZE,setController); 
    264262                addControllerListener(ControllerEvent.SEEK,setController); 
     
    279277                addViewListener(ViewEvent.PLAY,setView); 
    280278                addViewListener(ViewEvent.PREV,setView); 
    281                 addViewListener(ViewEvent.QUALITY,setView); 
    282279                addViewListener(ViewEvent.REDRAW,setView); 
    283280                addViewListener(ViewEvent.SEEK,setView); 
  • trunk/as3/com/jeroenwijering/plugins/Accessibility.as

    r132 r135  
    2121 
    2222 
    23  
    2423        /** List with configuration settings. **/ 
    25         private var config:Object = { 
     24        public var config:Object = { 
    2625                audio:undefined, 
    2726                captions:undefined, 
     
    5049 
    5150 
    52  
    5351        public function Accessibility():void { 
    5452                loader = new URLLoader(); 
     
    5856 
    5957        /** Show/hide the captions **/ 
    60         public function hideCaptions(stt:Boolean) { 
    61                 config['hide'] = !stt; 
     58        public function hide(stt:Boolean) { 
     59                config['hide'] = stt; 
    6260                clip.visible = config['hide']; 
    6361                if(config['hide']) {  
     
    7169        /** Clicking the  hide button. **/ 
    7270        private function hideClick(evt:MouseEvent) { 
    73                 hideCaptions(config['hide']); 
     71                hide(!config['hide']); 
    7472        }; 
    7573 
     
    7876        public function initializePlugin(vie:AbstractView):void { 
    7977                view = vie; 
    80                 if(view.skin['accessibility']) { 
    81                         clip =  view.skin['accessibility']; 
    82                 } else {  
    83                         clip = this['accessibility']; 
    84                 } 
    85                 loadVars(); 
    8678                view.addControllerListener(ControllerEvent.ITEM,itemHandler); 
    8779                view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 
    8880                view.addModelListener(ModelEvent.TIME,timeHandler); 
    8981                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']; 
    9683                clip.tf.autoSize = TextFieldAutoSize.CENTER; 
    9784                format = new TextFormat(null,config['fontsize']); 
    98                 hideCaptions(config['hide']) 
    99                 muteAudio(config['mute']); 
     85                hide(config['hide']); 
     86                mute(config['mute']); 
    10087                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(); 
    10789                } 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) {} 
    11096        }; 
    11197 
     
    143129 
    144130 
    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  
    158131        /** Mute/unmute the audiodesc. **/ 
    159         private function muteAudio(stt:Boolean) { 
     132        public function mute(stt:Boolean) { 
    160133                config['mute'] = stt; 
    161134                setVolume(); 
     
    170143        /** Clicking the  hide button. **/ 
    171144        private function muteClick(evt:MouseEvent) { 
    172                 muteAudio(!config['mute']); 
     145                mute(!config['mute']); 
    173146        }; 
    174147 
     
    183156 
    184157        /** Set the audidescription volume level. **/ 
    185         public function setAudio():void { 
     158        private function setAudio():void { 
    186159                sound = new Sound(new URLRequest(config['audio'])); 
    187160                channel = sound.play(); 
    188161                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                } 
    189176        }; 
    190177 
  • trunk/as3/com/jeroenwijering/plugins/ClickProxy.as

    r132 r135  
    1515 
    1616        /** Configuration values of the plugin. **/ 
    17         private var config:Object = { 
     17        public var config:Object = { 
    1818                listener:'clickListener' 
    1919        }; 
     
    6161                clip.buttonMode = true; 
    6262                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(); 
    6864        }; 
    6965 
    7066 
    7167        /** Resize the area. **/ 
    72         private function resizeHandler(evt:ControllerEvent=undefined) { 
     68        private function resizeHandler(evt:ControllerEvent=null) { 
    7369                clip.back.width = view.config['width']; 
    7470                clip.back.height = view.config['height']; 
  • trunk/as3/com/jeroenwijering/plugins/Controlbar.as

    r127 r135  
    88import com.jeroenwijering.utils.*; 
    99 
     10import flash.accessibility.*; 
    1011import flash.display.*; 
    1112import flash.events.MouseEvent; 
     
    2627        private var bar:MovieClip; 
    2728        /** List with configuration settings. **/ 
    28         private var config:Object; 
     29        public var config:Object; 
    2930        /** A list with all controls. **/ 
    3031        private var stacker:Stacker; 
     
    5051                unmuteButton:'MUTE' 
    5152        }; 
    52         /** The actions for all sliders **/  
     53        /** The actions for all sliders **/ 
    5354        private var SLIDERS = { 
    5455                timeSlider:'SEEK', 
     
    6667        public function initializePlugin(vie:AbstractView):void { 
    6768                view = vie; 
    68                 config = view.getPluginConfig(this); 
    6969                view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 
    7070                view.addModelListener(ModelEvent.LOADED,loadedHandler); 
     
    8080                setColors(); 
    8181                itemHandler(); 
     82                loadedHandler(); 
    8283                muteHandler(); 
     84                stateHandler(); 
     85                timeHandler(); 
    8386                volumeHandler(); 
    84                 loadedHandler(); 
    85                 timeHandler(); 
    86                 stateHandler(); 
    8787        }; 
    8888 
     
    9797        public function addButton(icn:DisplayObject,nam:String,hdl:Function):void { 
    9898                if(bar['linkButton'].back) { 
    99                         var btn:MovieClip = Draw.clone(bar['linkButton']); 
     99                        var btn = Draw.clone(bar['linkButton']); 
    100100                        btn.name = nam+'Button'; 
    101101                        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; 
    102107                        bar.addChild(btn); 
    103108                        var off:Number = Math.round((btn.height-icn.height)/2); 
     
    159164        private function itemHandler(evt:ControllerEvent=null):void { 
    160165                try { 
    161                         if(view.playlist && view.playlist.length > 1) { 
     166                        if(view.playlist && view.playlist.length > 1 && view.config['playlist'] != 'none') { 
    162167                                bar.prevButton.visible = bar.nextButton.visible = true; 
    163168                        } else { 
     
    193198                        bar.timeSlider.mark.x = pc2*wid; 
    194199                        bar.timeSlider.mark.width = pc1*wid; 
     200                        var icw:Number = bar.timeSlider.icon.x + bar.timeSlider.icon.width; 
    195201                } catch (err:Error) {} 
    196202        }; 
     
    266272                bar.visible = config['visible']; 
    267273                if(config['position'] == 'over' || view.config['fullscreen'] == true) { 
    268                         bar.x = config['margin']; 
     274                        bar.x = config['x'] + config['margin']; 
    269275                        bar.y = config['y'] + config['height'] - config['margin'] - config['size']; 
    270276                        wid = config['width'] - 2*config['margin']; 
     
    318324        /** Init the colors. **/ 
    319325        private function setColors():void { 
    320                 if(view.config['backcolor'] && bar['playButton'].icon) {  
     326                if(view.config['backcolor'] && bar['playButton'].icon) { 
    321327                        var clr:ColorTransform = new ColorTransform(); 
    322328                        clr.color = uint('0x'+view.config['backcolor'].substr(-6)); 
     
    401407                } else if(view.playlist) { 
    402408                        dur = view.playlist[view.config['item']]['duration']; 
    403                         pos = view.playlist[view.config['item']]['start']; 
     409                        pos = 0; 
    404410                } 
    405411                var pct:Number = pos/dur; 
     
    414420                                bar.timeSlider.icon.visible = true; 
    415421                                bar.timeSlider.mark.visible = true; 
     422                                bar.timeSlider.done.visible = true; 
    416423                                if(!scrubber) { 
    417424                                        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; 
    426426                                } 
    427427                        } else { 
     
    452452        /** Reflect the new volume in the controlbar **/ 
    453453        private function volumeHandler(evt:ControllerEvent=null):void { 
    454                 try {  
     454                try { 
    455455                        var vsl:MovieClip = bar.volumeSlider; 
    456456                        vsl.mark.width = view.config['volume']*(vsl.rail.width-vsl.icon.width/2)/100; 
  • trunk/as3/com/jeroenwijering/plugins/Display.as

    r132 r135  
    88import com.jeroenwijering.utils.Draw; 
    99import 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 
     11import flash.display.*; 
     12import flash.events.*; 
    1513import flash.geom.ColorTransform; 
    1614import flash.net.URLRequest; 
    17 import flash.utils.clearTimeout; 
    18 import flash.utils.setTimeout; 
     15import flash.utils.*; 
    1916 
    2017 
     
    2219 
    2320 
     21        /** Configuration vars for this plugin. **/ 
     22        public var config:Object; 
    2423        /** Reference to the MVC view. **/ 
    2524        private var view:AbstractView; 
     
    2827        /** Loader object for loading a logo. **/ 
    2928        private var loader:Loader; 
    30         /** Configuration vars for this plugin. **/ 
    31         private var config:Object; 
    3229        /** The margins of the logo. **/ 
    3330        private var margins:Array; 
     
    4441                'nextIcon' 
    4542        ); 
    46         /** ID for the buffer showing tiomeout. **/ 
     43        /** Timeout for hiding the buffericon. **/ 
    4744        private var timeout:Number; 
    4845 
     
    5552        public function initializePlugin(vie:AbstractView):void { 
    5653                view = vie; 
    57                 config = view.getPluginConfig(this); 
    5854                view.addControllerListener(ControllerEvent.ERROR,errorHandler); 
     55                view.addControllerListener(ControllerEvent.MUTE,stateHandler); 
     56                view.addControllerListener(ControllerEvent.PLAYLIST,stateHandler); 
    5957                view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 
    60                 view.addControllerListener(ControllerEvent.PLAYLIST,stateHandler); 
    6158                view.addModelListener(ModelEvent.BUFFER,bufferHandler); 
    6259                view.addModelListener(ModelEvent.ERROR,errorHandler); 
     
    6966                        display.back.transform.colorTransform = clr; 
    7067                } 
    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                 } 
    7668                if(view.config['displayclick'] != 'none') { 
    7769                        display.addEventListener(MouseEvent.CLICK,clickHandler); 
     
    7971                        display.mouseChildren = false; 
    8072                } 
    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                } 
    8976                stateHandler(); 
    9077        }; 
     
    9380        /** Receive buffer updates. **/ 
    9481        private function bufferHandler(evt:ModelEvent):void { 
    95                 var pct:String = ''; 
    9682                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                } 
    10287        }; 
    10388 
     
    10590        /** Process a click on the display. **/ 
    10691        private function clickHandler(evt:MouseEvent):void { 
    107                 if(view.config['state'] == ModelStates.IDLE) {  
     92                if(view.config['state'] == ModelStates.IDLE) { 
    10893                        view.sendEvent('PLAY'); 
    109                 } else {  
     94                } else if (view.config['state'] == ModelStates.PLAYING && view.config['mute'] == true) { 
     95                        view.sendEvent('MUTE'); 
     96                } else { 
    11097                        view.sendEvent(view.config['displayclick']); 
    11198                } 
     
    116103        private function errorHandler(evt:Object):void { 
    117104                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); 
    122107                } 
    123108        }; 
     
    139124 
    140125 
    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  
    182126        /** Setup the logo loading. **/ 
    183         private function setLogo():void { 
     127        private function logoSetter():void { 
    184128                margins = new Array( 
    185129                        display.logo.x, 
     
    188132                        display.back.height-display.logo.y-display.logo.height 
    189133                ); 
    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                } 
    194179        }; 
    195180 
     
    197182        /** Handle a change in playback state. **/ 
    198183        private function stateHandler(evt:Event=null):void { 
    199                 clearTimeout(timeout); 
    200184                switch (view.config['state']) { 
    201185                        case ModelStates.PLAYING: 
    202                                 setIcon(); 
     186                                if(view.config['mute'] == true) { 
     187                                        setIcon('muteIcon'); 
     188                                } else { 
     189                                        setIcon(); 
     190                                } 
    203191                                break; 
    204192                        case ModelStates.BUFFERING: 
    205                                 if(evt && evt['data']['oldstate'] == ModelStates.PLAYING) { 
    206                                         setIcon(); 
     193                                if(evt && evt['data'].oldstate == ModelStates.PLAYING) { 
    207194                                        timeout = setTimeout(setIcon,1500,'bufferIcon'); 
    208195                                } else { 
     
    213200                                if(view.config.displayclick == 'none' || !view.playlist) { 
    214201                                        setIcon(); 
    215                                 } else {  
     202                                } else { 
    216203                                        setIcon('playIcon'); 
    217204                                } 
  • trunk/as3/com/jeroenwijering/plugins/HD.as

    r132 r135  
    1515 
    1616        /** List with configuration settings. **/ 
    17         private var config:Object; 
     17        public var config:Object; 
    1818        /** Reference to the View of the player. **/ 
    1919        private var view:AbstractView; 
     
    2626 
    2727 
    28         /** Quality is clicked, so change the video. **/ 
     28        /** HD button is clicked, so change the video. **/ 
    2929        private function clickHandler(evt:MouseEvent=null):void { 
    30                 if(config['state']) {  
     30                if(config['state']) { 
    3131                        config['state'] = false; 
    3232                } else {  
     
    4747                view.addControllerListener(ControllerEvent.PLAYLIST,playlistHandler); 
    4848                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 { 
    5849                        view.getPlugin('controlbar').addButton(icon,'hd',clickHandler); 
    5950                } catch (err:Error) { 
    6051                        icon.visible = false; 
    6152                } 
     53                if(config['state'] == true) { 
     54                        original = view.config['file']; 
     55                        view.config['file'] = config['file']; 
     56                } 
     57                setButton(); 
    6258        }; 
    6359 
     
    7268 
    7369 
    74         /** Reload the playlist with either the HD or default videos. **/ 
     70        /** Reload the playlist with either the HD or default video. **/ 
    7571        private function reLoad():void { 
    76                 var ply = view.playlist; 
     72                var fil:String; 
     73                var ply:Array = view.playlist; 
    7774                if(config['state'] == true) { 
    78                         ply[0]['file'] = config['file']; 
     75                        fil = config['file']; 
    7976                } else { 
    80                         ply[0]['file'] = original; 
     77                        fil = original; 
    8178                } 
    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                } 
    8385        }; 
    8486 
     
    9193                        icon.alpha = 0.3; 
    9294                } 
    93         } 
     95        }; 
    9496 
    9597 
  • trunk/as3/com/jeroenwijering/plugins/MetaViewer.as

    r132 r135  
    1414 
    1515 
     16        /** Object with configuration values. **/ 
     17        public var config:Object; 
    1618        /** Reference to the View of the player. **/ 
    1719        private var view:AbstractView; 
     
    2022        /** Scrollbar clip for the metadata. **/ 
    2123        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."; 
    2428 
    2529 
     
    2933                clip.tf.mask = clip.ms; 
    3034                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); 
    3440                scrollbar = new Scrollbar(clip.tf,clip.ms); 
    3541        }; 
    3642 
    3743 
    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; 
    4447        }; 
    4548 
    4649 
    47         /** When clicking the x, the viewer is closed. **/ 
    48         private function clickHandler(evt:MouseEvent) { clip.visible = false; }; 
    49  
    50  
    5150        /** Print the metadata in a list. **/ 
    52         private function metaHandler(evt:ModelEvent) { 
     51        private function dataHandler(evt:ModelEvent) { 
    5352                if(evt.data.type == 'metadata' || evt.data.type == 'id3') { 
    54                         var str:String = ''; 
     53                        var arr:Array = new Array(); 
    5554                        for (var itm:String in evt.data) { 
    5655                                switch(itm) { 
     
    6160                                                break; 
    6261                                        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                                                } 
    6467                                                break; 
    6568                                        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                                                } 
    6673                                        case 'trackinfo': 
    67                                                 str += '» '+itm+': '+evt.data[itm].length+' entries\n'; 
     74                                                arr.push('» '+itm+': '+evt.data[itm].length+' entries'); 
    6875                                                break; 
    6976                                        default: 
    7077                                                if(evt.data[itm] != '') { 
    71                                                         str += '» '+itm+': '+evt.data[itm]+'\n'; 
     78                                                        arr.push('» '+itm+': '+evt.data[itm]); 
    7279                                                } 
    7380                                                break; 
    7481                                } 
    7582                        } 
    76                         clip.tf.text = str; 
    77                         clip.visible = true; 
    78                         scrollbar.draw(); 
     83                        arr.sort(); 
     84                        metastring = arr.join('\n'); 
     85                        metaHandler(); 
     86                        resizeHandler(); 
    7987                } 
     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(); 
    80106        }; 
    81107 
     
    85111                var wid:Number = view.config['width']; 
    86112                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; 
    95120                        } 
    96                 } catch(err:Error) {} 
     121                        clip.visible = config['visible']; 
     122                } 
    97123                clip.bg.width = wid; 
    98124                clip.bg.height = hei; 
    99125                clip.tf.width = clip.ms.width = wid-50; 
    100126                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; 
    102137                scrollbar.draw(); 
    103138        }; 
  • trunk/as3/com/jeroenwijering/plugins/Playlist.as

    r132 r135  
    2020 
    2121 
     22        /** List with configuration settings. **/ 
     23        public var config:Object; 
    2224        /** Reference to the view. **/ 
    2325        private var view:AbstractView; 
    2426        /** Reference to the playlist MC. **/ 
    2527        private var clip:MovieClip; 
    26         /** List with configuration settings. **/ 
    27         private var config:Object; 
    2828        /** Array with all button instances **/ 
    2929        private var buttons:Array; 
     
    5252        public function initializePlugin(vie:AbstractView):void { 
    5353                view = vie; 
    54                 config = view.getPluginConfig(this); 
    5554                view.addControllerListener(ControllerEvent.ITEM,itemHandler); 
    5655                view.addControllerListener(ControllerEvent.PLAYLIST,playlistHandler); 
     
    300299                                continue; 
    301300                        } else if(itm == 'image') { 
    302                                 if(view.playlist[idx]['image']) { 
     301                                if(view.playlist[idx]['image'] && config['thumbs'] != false) { 
    303302                                        var img:MovieClip = buttons[idx].c.image; 
    304303                                        var msk:Sprite = Draw.rect(buttons[idx].c,'0xFF0000',img.width,img.height,img.x,img.y); 
     
    327326                        } 
    328327                } 
    329                 if(buttons[idx].c['image'] && !view.playlist[idx]['image']) { 
     328                if(buttons[idx].c['image'] && (!view.playlist[idx]['image'] || config['thumbs'] == false)) { 
    330329                        buttons[idx].c['image'].visible = false; 
    331330                } 
  • trunk/as3/com/jeroenwijering/plugins/Revolt.as

    r132 r135  
    99import com.anttikupila.revolt.presets.*; 
    1010import com.jeroenwijering.events.*; 
     11import com.jeroenwijering.utils.Randomizer; 
    1112 
    1213import flash.media.*; 
     
    2021 
    2122 
    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. **/ 
    2337        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; 
    3046 
    3147 
    3248        /** Setup all presets and the click. **/ 
    3349        public function Revolt() { 
    34                 presetList = new Array( 
     50                presets = new Array( 
    3551                        new LineFourier(), 
    36                         new LineNoFourier(), 
    3752                        new Explosion(), 
    3853                        new LineSmooth(), 
     
    4055                        new Tunnel() 
    4156                ); 
    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); 
    5258        }; 
    5359 
     
    5864                view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 
    5965                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); 
    6279                pic.smoothing = true; 
    6380                clip.addChild(pic); 
    6481                resizeHandler(); 
     82                if(config['simple'] == true) {  
     83                        current = new LineNoFourier(view.config['lightcolor']); 
     84                } else { 
     85                        next(); 
     86                } 
    6587        }; 
     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        } 
    6698 
    6799 
    68100        /** Compute a new soundspectrum bitmap. **/ 
    69101        private function compute(ev:Event):void { 
    70                 SoundMixer.computeSpectrum(ba,preset.fourier,0); 
     102                SoundMixer.computeSpectrum(array,current.fourier,0); 
    71103                var soundArray:Array = new Array(); 
    72104                for (var i:uint = 0; i < 512; i++) { 
    73                         soundArray.push(ba.readFloat()); 
     105                        soundArray.push(array.readFloat()*config['gain']); 
    74106                } 
    75                 preset.applyGfx(gfx,soundArray); 
     107                current.applyGfx(bitmap,soundArray); 
    76108        }; 
    77109 
    78110 
    79111        /** 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); 
    91118                } 
    92119        }; 
     
    95122        /** Resize the visualizer to the display. **/ 
    96123        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 { 
    104130                        clip.width = view.config['width']; 
    105131                        clip.height = view.config['height']; 
     
    111137        private function stateHandler(evt:ModelEvent=null) { 
    112138                removeEventListener(Event.ENTER_FRAME,compute); 
     139                clearTimeout(timeout); 
    113140                switch(view.config['state']) { 
    114141                        case ModelStates.BUFFERING: 
    115142                        case ModelStates.PAUSED: 
    116143                        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                                } 
    120152                                break; 
    121153                        default: 
    122                                 presetInt.reset(); 
    123154                                clip.visible = false; 
    124155                                break; 
  • trunk/as3/com/jeroenwijering/plugins/Rightclick.as

    r88 r135  
    11/** 
    2 * Wrap all views and plugins and provides them with MVC access pointers. 
     2* Implement a rightclick menu with "fullscreen", "stretching" and "about" options. 
    33**/ 
    44package com.jeroenwijering.plugins { 
     
    66 
    77import com.jeroenwijering.events.*; 
     8 
    89import flash.events.ContextMenuEvent; 
    910import flash.net.URLRequest; 
     
    1617 
    1718 
     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; 
    1827        /** Reference to the MVC view. **/ 
    1928        private var view:AbstractView; 
    20         /** Reference to the contextmenu. **/ 
    21         private var context:ContextMenu; 
    2229 
    2330 
    2431        /** 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        }; 
    2649 
    2750 
     
    2952        public function initializePlugin(vie:AbstractView):void { 
    3053                view = vie; 
    31                 context = new ContextMenu(); 
    32                 context.hideBuiltInItems(); 
    3354                view.skin.contextMenu = context; 
    34                 qualityItem(); 
    3555                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                        } 
    3760                } 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); 
    4663                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']+'...'); 
    4867                } 
    49                 itm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,aboutSetter); 
    50                 itm.separatorBefore = true; 
    51                 context.customItems.push(itm); 
     68                addItem(about,aboutHandler); 
    5269        }; 
    5370 
    5471 
    5572        /** jump to the about page. **/ 
    56         private function aboutSetter(evt:ContextMenuEvent):void { 
     73        private function aboutHandler(evt:ContextMenuEvent):void { 
    5774                navigateToURL(new URLRequest(view.config['aboutlink']),'_blank'); 
    5875        }; 
    5976 
    6077 
    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  
    8178        /** Toggle the fullscreen mode. **/ 
    82         private function fullscreenSetter(evt:ContextMenuEvent):void {  
     79        private function fullscreenHandler(evt:ContextMenuEvent):void {  
    8380                view.sendEvent('fullscreen'); 
    8481        }; 
    8582 
    8683 
    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                        } 
    9391                } 
    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'); 
    11396        }; 
    11497 
  • trunk/as3/com/jeroenwijering/plugins/SoundProxy.as

    r132 r135  
    1717 
    1818 
    19         /** initialize call for 4.0 backward compatibility. **/ 
    20         public var initialize:Function = initializePlugin; 
    2119        /** Reference to the View of the player. **/ 
    2220        private var view:AbstractView; 
    2321        /** Configuration values of the plugin. **/ 
    24         private var config:Object = { 
     22        public var config:Object = { 
    2523                bands:1, 
    2624                interval:100, 
     
    2927        /** ID of the sample sending interval. **/ 
    3028        private var interval:Number; 
    31  
    3229 
    3330 
     
    5956                view = vie; 
    6057                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                 } 
    6658        }; 
    6759 
  • trunk/as3/com/jeroenwijering/utils/Draw.as

    r103 r135  
    2929 
    3030        /**  
    31         * Clone a displayobject. 
     31        * Clone a sprite / movieclip. 
    3232        * 
    33         * @param tgt    Displayobject to clone. 
     33        * @param tgt    Sprite to clone. 
    3434        * @param adc    Add as child to the parent displayobject. 
    3535        * 
    3636        * @return               The clone; not yet added to the displaystack. 
    3737        **/ 
    38         public static function clone(tgt:MovieClip,adc:Boolean=false):MovieClip { 
     38        public static function clone(tgt:Sprite,adc:Boolean=false):MovieClip { 
    3939                var cls:Class = Object(tgt).constructor; 
    40                 var dup:MovieClip = new cls(); 
     40                var dup = new cls(); 
    4141                dup.transform = tgt.transform; 
    4242                dup.filters = tgt.filters; 
     
    5050        }; 
    5151 
     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        }; 
    5265 
    53         /**  
     66 
     67        /** 
    5468        * Draw a rectangle on stage. 
    5569        * 
     
    7589 
    7690        /**  
     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        /**  
    77120        * Draw a textfield on stage. 
    78121        * 
     
    86129        * @param xps    X offset of the textfield,defaults to 0. 
    87130        * @param yps    Y offset of the textfield, defaults to 0. 
     131        * @param ats    Autosize text alignment. 
    88132        * 
    89133        * @return               A reference to the textfield. 
    90134        **/ 
    91135        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 { 
    93137                var tfd:TextField = new TextField(); 
    94138                var fmt:TextFormat = new TextFormat(); 
     
    99143                        tfd.multiline = true; 
    100144                        tfd.wordWrap = true; 
     145                } else {  
     146                        tfd.autoSize = ats; 
    101147                } 
    102148                tfd.x = xps; 
  • trunk/as3/com/jeroenwijering/utils/Stretcher.as

    r106 r135  
    4747                                break; 
    4848                        case 'none': 
     49                                clp.scaleX = 1; 
     50                                clp.scaleY = 1; 
    4951                                break; 
    5052                        case 'uniform': 
  • trunk/as3/yt.as

    r134 r135  
    1 // Security domains 
     1// Security domains 
    22System.security.allowDomain('*'); 
    33System.security.allowInsecureDomain('*'); 
     
    66 
    77// Variables 
     8if(!unique) { var unique = 1; } 
    89var ytPlayer:MovieClip = this.createEmptyMovieClip("ytPlayer",this.getNextHighestDepth()); 
    910var ytPlayerLoader:MovieClipLoader = new MovieClipLoader(); 
     
    8990 
    9091// Initialization 
    91 unique; 
    92 trace(unique); 
    9392_as3_to_as2.connect('AS3_'+unique); 
    9493ytPlayerLoaderListener = {};  
     
    9695ytPlayerLoader.addListener(ytPlayerLoaderListener); 
    9796ytPlayerLoader.loadClip(ytLocation,ytPlayer); 
    98  
Note: See TracChangeset for help on using the changeset viewer.