Changeset 374


Ignore:
Timestamp:
09/20/09 18:16:22 (4 years ago)
Author:
jeroen
Message:

implemented bitrate switching for rtmp/http/video. Also updated testmovies to use Edgecast / Bitgravity

Files:
1 added
5 deleted
40 edited
1 copied

Legend:

Unmodified
Added
Removed
  • plugins/livestream/com/jeroenwijering/plugins/Livestream.as

    r217 r374  
    5050        public function Livestream():void { 
    5151                connection = new NetConnection(); 
     52                connection.client = new Object(); 
    5253                buildStage(); 
    5354        }; 
     
    157158                                Logger.log('no livestream yet: '+evt.info.code,'livestream'); 
    158159                                break; 
     160                        default: 
     161                                Logger.log(evt.info,'livestream'); 
     162                                break; 
    159163                } 
    160164        }; 
  • plugins/qualitymonitor/com/jeroenwijering/plugins/QualityMonitor.as

    r338 r374  
    44import com.jeroenwijering.events.*; 
    55 
     6 
    67import flash.display.*; 
    78import flash.events.*; 
    89import flash.geom.Rectangle; 
    910import flash.text.*; 
     11import flash.utils.*; 
     12 
    1013 
    1114/** 
    12 * A simple plugin that displays a search bar. 
     15* Show bitrate switching events. 
    1316**/ 
    1417public class QualityMonitor extends MovieClip implements PluginInterface { 
     
    1720        /** Reference to the background clip. **/ 
    1821        private var back:Sprite; 
    19         /** Reference to the graphics. **/ 
    20         public var config:Object = {}; 
     22        /** Configuration variables. **/ 
     23        public var config:Object ={}; 
    2124        /** Reference to the textfield. **/ 
    2225        private var field:TextField; 
     26        /** Reference to the checking interval. **/ 
     27        private var interval:Number; 
    2328        /** Reference to the view of the player. **/ 
    2429        private var view:AbstractView; 
     
    3136                back = new Sprite(); 
    3237                back.graphics.beginFill(0x000000,0.8); 
    33                 back.graphics.drawRect(0,0,400,30); 
     38                back.graphics.drawRect(0,0,400,60); 
    3439                addChild(back); 
    3540                field = new TextField(); 
    36                 var fmt:TextFormat = new TextFormat("_sans",11,0xFFFFFF); 
    37                 fmt.align = 'center'; 
    38                 field.defaultTextFormat = fmt; 
    39                 field.x = field.y = 5; 
    40                 field.htmlText = "Awaiting quality events"; 
     41                field.defaultTextFormat = new TextFormat("_sans",11,0xFFFFFF); 
     42                field.multiline = true; 
     43                field.x = 8; 
     44                field.y = 5; 
    4145                addChild(field); 
     46        }; 
     47 
     48 
     49        /** Update quality metrics **/ 
     50        private function check():void { 
     51                var len:Number = 1; 
     52                if(view.playlist[view.config['item']]['levels']) {  
     53                        len = view.playlist[view.config['item']]['levels'].length; 
     54                } 
     55                field.htmlText =  
     56                        '<b>bandwidth:</b> ' + view.config['bandwidth'] + ' kbps<br/>' + 
     57                        '<b>level:</b> ' + (view.config['level']+1) + ' of ' + len + '<br/>' + 
     58                        '<b>width:</b> '+ view.config['width'] + ' pixels'; 
    4259        }; 
    4360 
     
    4764                view = vie; 
    4865                view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 
    49                 view.addModelListener('QUALITY',qualityHandler); 
    50                 resizeHandler(new ControllerEvent(ControllerEvent.RESIZE)); 
    51         }; 
    52  
    53  
    54         /** Update quality metrics **/ 
    55         private function qualityHandler(evt:ModelEvent):void { 
    56                 var txt:String = ''; 
    57                 for(var i:String in evt.data) { 
    58                         txt +='<b>'+i+':</b> '+evt.data[i]+' | '; 
    59                 } 
    60                 field.htmlText = txt.substr(0,txt.length-2); 
     66                interval = setInterval(check,1000); 
    6167        }; 
    6268 
     
    6470        /** Handle a resize. **/ 
    6571        private function resizeHandler(evt:ControllerEvent):void { 
    66                 back.width = config['width']; 
    6772                x = config['x']; 
    6873                y = config['y']; 
    69                 field.width = back.width - 10; 
     74                back.width = config['width']; 
     75                field.width = config['width']-10; 
    7076        }; 
    7177 
  • plugins/qualitymonitor/qualitymonitor.xml

    r338 r374  
    1010        <href>http://developer.longtailvideo.com/trac/browser/plugins/qualitymonitor</href> 
    1111 
    12         <flashvars> 
    13                 <flashvar> 
    14                         <name>position</name> 
    15                         <default>over</default> 
    16                         <description>Position of the plugin.</description> 
    17                 </flashvar> 
    18         </flashvars> 
     12        <flashvars /> 
    1913 
    2014</plugin> 
  • plugins/searchbar/com/jeroenwijering/plugins/Searchbar.as

    r260 r374  
    2424                size:40, 
    2525                label:'Search', 
    26                 position:'over', 
     26                position:'bottom', 
    2727                script:'http://gdata.youtube.com/feeds/api/videos?vq=QUERY&format=5' 
    2828        }; 
  • testing/files/bitrates.xml

    r204 r374  
    1 <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"> 
     1<rss version="2.0" 
     2        xmlns:media="http://search.yahoo.com/mrss/"  
     3        xmlns:jwplayer="http://developer.longtailvideo.com/trac/wiki/FlashFormats"> 
    24        <channel> 
    3                 <title>Example media RSS playlist for the JW Player</title> 
    4                 <link>http://developer.longtailvideo.com/trac</link> 
     5                <title>Playlist with bitrate switches</title> 
    56 
    67                <item> 
    7                         <title>Opening credits</title> 
    8                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="00:00" /> 
    9                         <description>In which we meet Proog and Emo, the two characters of this movie.</description> 
    10                         <link>http://orange.blender.org/</link> 
     8                        <title>Progressive download</title> 
     9                        <description>When bitrate switching a progressive download, the only actual switch is done on startup.</description> 
     10                        <media:group> 
     11                                <media:content bitrate="1500" width="1080" url="http://content.bitsontherun.com/videos/8Juv1MVa-67727.mp4" /> 
     12                                <media:content bitrate="1100" width="720" url="http://content.bitsontherun.com/videos/8Juv1MVa-485.mp4" /> 
     13                                <media:content bitrate="700" width="480" url="http://content.bitsontherun.com/videos/8Juv1MVa-484.mp4" /> 
     14                                <media:content bitrate="400" width="320" url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" /> 
     15                                <media:thumbnail url="http://content.bitsontherun.com/thumbs/8Juv1MVa-480.jpg" /> 
     16                        </media:group> 
    1117                </item> 
    1218 
    1319                <item> 
    14                         <title>Wire attack</title> 
    15                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="00:26" /> 
    16                         <description>In which the computer world of our actors is being introduced.</description> 
    17                         <link>http://orange.blender.org/</link> 
     20                        <title>HTTP streaming</title> 
     21                        <description>Bitrate switching for HTTP streaming is done on startup and with every seek and fullscreen switch.</description> 
     22                        <media:content bitrate="1500" width="1080" url="http://content.bitsontherun.com/videos/8Juv1MVa-67727.mp4" /> 
     23                        <media:content bitrate="1100" width="720" url="http://content.bitsontherun.com/videos/8Juv1MVa-485.mp4" /> 
     24                        <media:content bitrate="700" width="480" url="http://content.bitsontherun.com/videos/8Juv1MVa-484.mp4" /> 
     25                        <media:content bitrate="400" width="320" url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" /> 
     26                        <media:thumbnail url="http://content.bitsontherun.com/thumbs/8Juv1MVa-480.jpg" /> 
     27                        <jwplayer:type>http</jwplayer:type> 
     28                        <jwplayer:streamer>starttime</jwplayer:streamer> 
    1829                </item> 
    1930 
    2031                <item> 
    21                         <title>The bird cave</title> 
    22                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="01:10" /> 
    23                         <description>In which Proog takes upon his role as a guide and savely sees Emo across.</description> 
    24                         <link>http://orange.blender.org/</link> 
    25                 </item> 
    26  
    27                 <item> 
    28                         <title>Answer the phone</title> 
    29                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="02:30" /> 
    30                         <description>In which Emo and Proog have their first argument.</description> 
    31                         <link>http://orange.blender.org/</link> 
    32                 </item> 
    33  
    34                 <item> 
    35                         <title>Across the gap</title> 
    36                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="03:44" /> 
    37                         <description>In which we learn that not everything here is what it looks like.</description> 
    38                         <link>http://orange.blender.org/</link> 
    39                 </item> 
    40  
    41                 <item> 
    42                         <title>Elevator Ride</title> 
    43                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="04:53" /> 
    44                         <description>In which Proog and Emo jump into space, and fall back again.</description> 
    45                         <link>http://orange.blender.org/</link> 
    46                 </item> 
    47  
    48                 <item> 
    49                         <title>Final Conflict</title> 
    50                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="06:25" /> 
    51                         <description>In which Emo does not tolerate Proogs guidance anymore, with fatal consequence.</description> 
    52                         <link>http://orange.blender.org/</link> 
    53                 </item> 
    54  
    55                 <item> 
    56                         <title>Ending Credits</title> 
    57                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="09:25" /> 
    58                         <description>In which the huge list of contributers to this project passes by.</description> 
    59                         <link>http://orange.blender.org/</link> 
     32                        <title>RTMP streaming</title> 
     33                        <description>Bitrate switching for RTMP streaming is done on startup and with every seek and fullscreen switch.</description> 
     34                        <media:group> 
     35                                <media:content bitrate="1500" width="1080" url="videos/8Juv1MVa-67727.mp4" /> 
     36                                <media:content bitrate="1100" width="720" url="videos/8Juv1MVa-485.mp4" /> 
     37                                <media:content bitrate="700" width="480" url="videos/8Juv1MVa-484.mp4" /> 
     38                                <media:content bitrate="400" width="320" url="videos/8Juv1MVa-483.mp4" /> 
     39                                <media:thumbnail url="http://content.bitsontherun.com/thumbs/8Juv1MVa-480.jpg" /> 
     40                        </media:group> 
     41                        <jwplayer:type>rtmp</jwplayer:type> 
     42                        <jwplayer:streamer>rtmp://fms.12E5.edgecastcdn.net/0012E5</jwplayer:streamer> 
    6043                </item> 
    6144 
  • testing/files/chapters.xml

    r204 r374  
    1 <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"> 
     1<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" 
     2        xmlns:jwplayer="http://developer.longtailvideo.com/trac/wiki/FlashFormats"> 
    23        <channel> 
    34                <title>Example media RSS playlist for the JW Player</title> 
     
    67                <item> 
    78                        <title>Opening credits</title> 
    8                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="00:00" /> 
     9                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="00:00" /> 
    910                        <description>In which we meet Proog and Emo, the two characters of this movie.</description> 
    1011                        <link>http://orange.blender.org/</link> 
     12                        <jwplayer:type>bitgravity</jwplayer:type> 
    1113                </item> 
    1214 
    1315                <item> 
    1416                        <title>Wire attack</title> 
    15                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="00:26" /> 
     17                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="00:26" /> 
    1618                        <description>In which the computer world of our actors is being introduced.</description> 
    1719                        <link>http://orange.blender.org/</link> 
     20                        <jwplayer:type>bitgravity</jwplayer:type> 
    1821                </item> 
    1922 
    2023                <item> 
    2124                        <title>The bird cave</title> 
    22                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="01:10" /> 
     25                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="01:10" /> 
    2326                        <description>In which Proog takes upon his role as a guide and savely sees Emo across.</description> 
    2427                        <link>http://orange.blender.org/</link> 
     28                        <jwplayer:type>bitgravity</jwplayer:type> 
    2529                </item> 
    2630 
    2731                <item> 
    2832                        <title>Answer the phone</title> 
    29                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="02:30" /> 
     33                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="02:30" /> 
    3034                        <description>In which Emo and Proog have their first argument.</description> 
    3135                        <link>http://orange.blender.org/</link> 
     36                        <jwplayer:type>bitgravity</jwplayer:type> 
    3237                </item> 
    3338 
    3439                <item> 
    3540                        <title>Across the gap</title> 
    36                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="03:44" /> 
     41                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="03:44" /> 
    3742                        <description>In which we learn that not everything here is what it looks like.</description> 
    3843                        <link>http://orange.blender.org/</link> 
     44                        <jwplayer:type>bitgravity</jwplayer:type> 
    3945                </item> 
    4046 
    4147                <item> 
    4248                        <title>Elevator Ride</title> 
    43                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="04:53" /> 
     49                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="04:53" /> 
    4450                        <description>In which Proog and Emo jump into space, and fall back again.</description> 
    4551                        <link>http://orange.blender.org/</link> 
     52                        <jwplayer:type>bitgravity</jwplayer:type> 
    4653                </item> 
    4754 
    4855                <item> 
    4956                        <title>Final Conflict</title> 
    50                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="06:25" /> 
     57                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="06:25" /> 
    5158                        <description>In which Emo does not tolerate Proogs guidance anymore, with fatal consequence.</description> 
    5259                        <link>http://orange.blender.org/</link> 
     60                        <jwplayer:type>bitgravity</jwplayer:type> 
    5361                </item> 
    5462 
    5563                <item> 
    5664                        <title>Ending Credits</title> 
    57                         <media:content url="http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/LJSVMnCF-326.flv" type="video/x-flv" start="09:25" /> 
     65                        <media:content url="http://content.bitsontherun.com/videos/8Juv1MVa-483.mp4" type="video/mp4" start="09:25" /> 
    5866                        <description>In which the huge list of contributers to this project passes by.</description> 
    5967                        <link>http://orange.blender.org/</link> 
     68                        <jwplayer:type>bitgravity</jwplayer:type> 
    6069                </item> 
    6170 
  • testing/files/style.css

    r185 r374  
    2525        background-color: #F5F5F5; 
    2626        border: 1px solid #7A2; 
     27} 
     28hr {  
     29        border:0;  
     30        clear: both; 
     31        display: block; 
     32        height: 10px; 
     33        width: 100%; 
    2734} 
    2835legend { 
  • testing/index.html

    r331 r374  
    380380        </fieldset> 
    381381        <fieldset id="layout"> 
    382                 <label>backcolor</label> 
    383                 <input type="text" name="backcolor" /> 
    384382                <label>controlbar</label> 
    385383                <input type="text" name="controlbar" /> 
    386                 <label>dock</label> 
    387                 <input type="text" name="dock" /> 
    388                 <label>frontcolor</label> 
    389                 <input type="text" name="frontcolor" /> 
    390384                <label>height</label> 
    391385                <input type="text" name="height" value="260" /> 
    392386                <label>icons</label> 
    393387                <input type="text" name="icons" /> 
    394                 <label>lightcolor</label> 
    395                 <input type="text" name="lightcolor" /> 
     388                <label>logo</label> 
     389                <input type="text" name="logo" /> 
    396390                <label>playlist</label> 
    397391                <input type="text" name="playlist" /> 
    398392                <label>playlistsize</label> 
    399393                <input type="text" name="playlistsize" /> 
     394                <label>width</label> 
     395                <input type="text" name="width" value="400" /> 
     396                <hr/> 
     397                <label>backcolor</label> 
     398                <input type="text" name="backcolor" /> 
     399                <label>frontcolor</label> 
     400                <input type="text" name="frontcolor" /> 
     401                <label>lightcolor</label> 
     402                <input type="text" name="lightcolor" /> 
    400403                <label>screencolor</label> 
    401404                <input type="text" name="screencolor" /> 
    402                 <label>width</label> 
    403                 <input type="text" name="width" value="400" /> 
    404405        </fieldset> 
    405406        <fieldset id="behaviour"> 
    406407                <label>autostart</label> 
    407408                <input type="text" name="autostart" /> 
     409                <label>bandwidth</label> 
     410                <input type="text" name="bandwidth" /> 
    408411                <label>bufferlength</label> 
    409412                <input type="text" name="bufferlength" /> 
    410413                <label>displayclick</label> 
    411414                <input type="text" name="displayclick" /> 
    412                 <label>displaytitle</label> 
    413                 <input type="text" name="displaytitle" /> 
     415                <label>dock</label> 
     416                <input type="text" name="dock" /> 
    414417                <label>item</label> 
    415418                <input type="text" name="item" /> 
    416419                <label>linktarget</label> 
    417420                <input type="text" name="linktarget" /> 
    418                 <label>logo</label> 
    419                 <input type="text" name="logo" /> 
    420421                <label>mute</label> 
    421422                <input type="text" name="mute" /> 
    422                 <label>oncomplete</label> 
    423                 <input type="text" name="oncomplete" /> 
    424423                <label>repeat</label> 
    425424                <input type="text" name="repeat" /> 
     
    440439                <label>id</label> 
    441440                <input type="text" name="id" /> 
    442                 <label>token</label> 
    443                 <input type="text" name="token" /> 
    444441        </fieldset> 
    445442        <span id="fieldsetspan"></span> 
  • testing/settings.js

    r341 r374  
    88                '4.2':'../tags/mediaplayer-4.2/player.swf', 
    99                '4.1':'../tags/mediaplayer-4.1/player.swf', 
    10                 '4.0':'../tags/mediaplayer-4.0/player.swf' 
     10                '4.0':'../tags/mediaplayer-4.0/player.swf', 
     11                'botr':'http://content.bitsontherun.com/staticfiles/videoplayer.swf' 
    1112        }, 
    1213        /** Available plugins to test. **/ 
     
    130131                10: {}, 
    131132                11: { 
     133                        title:'HTTP streamed FLV', 
     134                        file:'http://content.bitsontherun.com/videos/Qvxp3Jnv-68183.flv', 
     135                        type:'http', 
     136                        height:240, 
     137                        width:400 
     138                }, 
     139                12: { 
     140                        title:'HTTP streamed MP4', 
     141                        file:'http://content.bitsontherun.com/videos/Qvxp3Jnv-483.mp4', 
     142                        type:'bitgravity', 
     143                        height:240, 
     144                        width:400 
     145                }, 
     146                13: { 
     147                        title:'RTMP streamed FLV', 
     148                        file:'videos/Qvxp3Jnv-68183.flv', 
     149                        type:'rtmp', 
     150                        streamer:'rtmp://fms.12E5.edgecastcdn.net/0012E5', 
     151                        height:240, 
     152                        width:400 
     153                }, 
     154                14: { 
     155                        title:'RTMP streamed MP4', 
     156                        file:'videos/Qvxp3Jnv-483.mp4', 
     157                        type:'rtmp', 
     158                        streamer:'rtmp://fms.12E5.edgecastcdn.net/0012E5', 
     159                        height:240, 
     160                        width:400 
     161                }, 
     162                15: { 
     163                        title:'RTMP streamed MP3', 
     164                        file:'videos/Qvxp3Jnv-68182.mp3', 
     165                        type:'rtmp', 
     166                        streamer:'rtmp://fms.12E5.edgecastcdn.net/0012E5', 
     167                        height:240, 
     168                        width:400 
     169                }, 
     170                16: { 
     171                        title:'Smooth streamed MP4', 
     172                        file:'http://h264.code-shop.com:8080/bbb.mp4/bbb.ismc', 
     173                        type:'smooth', 
     174                        height:240, 
     175                        width:500 
     176                }, 
     177                20: {}, 
     178                21: { 
    132179                        title:'ASX playlist', 
    133180                        file:'files/asx.xml', 
     
    137184                        playlistsize:400 
    138185                }, 
    139                 12: { 
     186                22: { 
    140187                        title:'ATOM playlist', 
    141188                        file:'files/atom.xml', 
     
    145192                        playlistsize:400 
    146193                }, 
    147                 13: { 
     194                23: { 
    148195                        title:'iRSS playlist', 
    149196                        file:'files/irss.xml', 
     
    153200                        playlistsize:400 
    154201                }, 
    155                 14: { 
     202                24: { 
    156203                        title:'mRSS playlist', 
    157204                        file:'files/mrss.xml', 
     
    161208                        playlistsize:400 
    162209                }, 
    163                 15: { 
     210                25: { 
    164211                        title:'SMIL playlist', 
    165212                        file:'files/smil.xml', 
     
    169216                        playlistsize:400 
    170217                }, 
    171                 16: { 
     218                26: { 
    172219                        title:'XSPF playlist', 
    173220                        file:'files/xspf.xml', 
     
    177224                        playlistsize:400 
    178225                }, 
    179                 20: {}, 
    180                 21: { 
     226                30: {}, 
     227                31: { 
     228                        title:'Youtube playlist', 
     229                        file:'http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured?v=2', 
     230                        height:240, 
     231                        width:800, 
     232                        playlist:'right', 
     233                        playlistsize:400 
     234                }, 
     235                32: { 
     236                        title:'Multibitrate playlist', 
     237                        file:'files/bitrates.xml', 
     238                        height:240, 
     239                        width:800, 
     240                        playlist:'right', 
     241                        playlistsize:400, 
     242                        plugins:'qualitymonitor' 
     243                }, 
     244                33: { 
     245                        title:'Chapter playlist', 
     246                        file:'files/chapters.xml', 
     247                        height:240, 
     248                        width:800, 
     249                        playlist:'right', 
     250                        playlistsize:400 
     251                }, 
     252                40: {}, 
     253                41: { 
    181254                        title:'Different colors', 
    182                         file:'files/bunnies.xml', 
     255                        file:'files/mrss.xml', 
    183256                        height:240, 
    184257                        width:800, 
     
    190263                        screencolor:'FFFFFF' 
    191264                }, 
    192                 22: { 
     265                42: { 
    193266                        title:'Logo, title and no click', 
    194                         file:'files/bunnies.xml', 
     267                        file:'files/mrss.xml', 
    195268                        height:240, 
    196269                        width:800, 
     
    202275                        controlbar:'over' 
    203276                }, 
    204                 23: { 
     277                43: { 
    205278                        title:'Autostart, shuffle and repeat', 
    206                         file:'files/bunnies.xml', 
     279                        file:'files/mrss.xml', 
    207280                        repeat:'always', 
    208281                        height:240, 
     
    216289                        playlistsize:400 
    217290                }, 
    218                 24: { 
     291                44: { 
    219292                        title:'Stretched, stacked and muted', 
    220                         file:'files/bunnies.xml', 
     293                        file:'files/mrss.xml', 
    221294                        stretching:'fill', 
    222295                        height:240, 
     
    227300                        playlistsize:400 
    228301                }, 
    229                 25: { 
     302                45: { 
    230303                        title:'Loading from config xml', 
    231304                        config:'files/config.xml', 
     
    233306                        width:500 
    234307                }, 
    235                 26: { 
     308                46: { 
    236309                        title:'Start and duration flashvars', 
    237310                        file:'files/bunny.mp3', 
     
    243316                        autostart:'true' 
    244317                }, 
    245                 30: {}, 
    246                 33: { 
    247                         title:'HTTP streamed FLV', 
    248                         file:'bunny.flv', 
    249                         streamer:'http://www.longtailvideo.com/jw/embed/xmoov.php', 
    250                         type:'http', 
    251                         height:240, 
    252                         width:400 
    253                 }, 
    254                 34: { 
    255                         title:'Bitgravity streamed FLV', 
    256                         file:'http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/ntPYsD4L-326.flv', 
    257                         type:'bitgravity', 
    258                         displaytitle:'true', 
    259                         height:240, 
    260                         width:400 
    261                 }, 
    262                 35: { 
    263                         title:'Bitgravity streamed MP4', 
    264                         file:'http://bitcast-a.bitgravity.com/botr/ifNSlhVa/videos/ntPYsD4L-327.mp4', 
    265                         type:'bitgravity', 
    266                         height:240, 
    267                         width:400 
    268                 }, 
    269                 36: { 
    270                         title:'Highwinds streamed MP4', 
    271                         file:'http://hwcdn.net/i6s8g7u7/fms/ifNSlhVa/videos/YcCs0JoR-327.mp4', 
    272                         type:'highwinds', 
    273                         height:240, 
    274                         width:400 
    275                 }, 
    276                 37: { 
    277                         title:'Livestream demo', 
    278                         file:'http://www.livestream.com/builtin', 
    279                         height:240, 
    280                         width:400 
    281                 }, 
    282                 38: { 
    283                         title:'S3 Authenticated Video', 
    284                         file:'http%3A%2F%2Fcontent.longtailvideo.com%2Fvideos%2Fauthenticate.flv%3FAWSAccessKeyId%3DAKIAIMO2UYBVC6GA3WYQ%26Expires%3D1279755021%26Signature%3DOESMzl5TB%252Ff7rrSs18%252B52nPy9ww%253D', 
    285                         type:'video', 
    286                         height:240, 
    287                         width:400 
    288                 }, 
    289                 39: { 
    290                         title:'Smooth stream', 
    291                         file:'files/smooth.ismc', 
    292                         height:240, 
    293                         width:400 
    294                 }, 
    295318                50: {}, 
    296319                51: { 
     
    311334                }, 
    312335                53: { 
    313                         title:'Captions plugin (embedded captions)', 
    314                         file:'../../testing/files/bunny.mp4', 
    315                         height:240, 
    316                         width:500, 
    317                         plugins:'captions' 
     336                        title:'Infobox and logobox plugins', 
     337                        file:'files/mrss.xml', 
     338                        height:320, 
     339                        width:400, 
     340                        plugins:'infobox,logobox', 
     341                        'logobox.file':'files/watermark.png', 
     342                        'logobox.link':'http://www.longtailvideo.com', 
    318343                }, 
    319344                54: { 
     
    331356                        width:500, 
    332357                        plugins:'hd', 
    333                         'hd.file':'../../testing/files/bunny.m4v' 
     358                        'hd.file':'../../testing/files/bunny.mp4' 
    334359                }, 
    335360                56: { 
    336361                        title:'Livestream plugin', 
    337                         file:'../../testing/files/bunny.flv', 
     362                        file:'files/bunny.png', 
    338363                        height:260, 
    339364                        width:500, 
    340365                        plugins:'livestream', 
    341                         'livestream.file':'vdoxadmin/jeroen/bunny.flv', 
     366                        'livestream.file':'videos/Qvxp3Jnv-483.mp4', 
    342367                        'livestream.image':'files/bunny.jpg', 
    343                         'livestream.streamer':'rtmp://fl9.maelstrom.jet-stream.nl:80/vod/' 
     368                        'livestream.streamer':'rtmp://fms.12E5.edgecastcdn.net/0012E5' 
    344369                }, 
    345370                57: { 
     
    368393                        image:'files/bunny.jpg', 
    369394                        stretching:'fill', 
     395                        playlist:'over', 
    370396                        height:260, 
    371397                        width:460, 
    372                         plugins:'searchbar', 
    373                         'searchbar.script':'files/bunnies.xml' 
     398                        plugins:'searchbar' 
    374399                }, 
    375400                60: { 
     
    380405                        width:460, 
    381406                        plugins:'sharing', 
    382                         'sharing.code':'%3Cembed%20src%3D%22http%3A%2F%2Fcontent.bitsontherun.com%2Fplayers%2FnPripu9l-1754.swf%22%20width%3D%22400%22%20height%3D%22250%22%20allowscriptaccess%3D%22always%22%20%2F%3E', 
     407                        'sharing.code':'<embed src="http://content.bitsontherun.com/players/nPripu9l-1754.swf" width="400" height="250" allowscriptaccess="always" />', 
    383408                        'sharing.link':'http://www.bigbuckbunny.org/' 
    384409                }, 
    385410                61: { 
    386411                        title:'Snapshot plugin', 
    387                         file:'../../testing/files/bunny.m4v', 
     412                        file:'../../testing/files/bunny.mp4', 
    388413                        height:260, 
    389414                        width:600, 
    390415                        plugins:'snapshot', 
    391416                        'snapshot.script':'http://www.jeroenwijering.com/test/snapshot/create.php' 
    392                 }, 
    393                 62: { 
    394                         title:'Infobox and logobox plugins', 
    395                         file:'files/mrss.xml', 
    396                         height:320, 
    397                         width:400, 
    398                         plugins:'infobox,logobox', 
    399                         'logobox.file':'files/logobox.png', 
    400                         'logobox.link':'http://www.jamitnews.com', 
    401                 }, 
    402                 80: {}, 
    403                 81: { 
    404                         title:'Playlist with streamers', 
    405                         file:'files/streamers.xml', 
    406                         height:240, 
    407                         width:800, 
    408                         playlist:'right', 
    409                         playlistsize:400, 
    410                         frontcolor:'000000', 
    411                         lightcolor:'77AA22' 
    412                 }, 
    413                 82: { 
    414                         title:'Playlist with chapters', 
    415                         file:'files/chapters.xml', 
    416                         height:240, 
    417                         width:800, 
    418                         playlist:'right', 
    419                         playlistsize:400, 
    420                         streamer:'bitgravity', 
    421                         frontcolor:'000000', 
    422                         lightcolor:'77AA22' 
    423                 }, 
    424                 83:{ 
    425                         title:'Playlist from youtube', 
    426                         file:'http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured?v=2', 
    427                         height:240, 
    428                         width:800, 
    429                         playlist:'right', 
    430                         playlistsize:400 
    431417                } 
    432418        } 
  • trunk/as3/com/jeroenwijering/events/ModelEvent.as

    r338 r374  
    1818        public static var LOADED:String = "LOADED"; 
    1919        public static var META:String = "META"; 
    20         public static var QUALITY:String = "QUALITY"; 
    2120        public static var STATE:String = "STATE"; 
    2221        public static var TIME:String = "TIME"; 
  • trunk/as3/com/jeroenwijering/models/AbstractModel.as

    r166 r374  
    77import com.jeroenwijering.events.*; 
    88import com.jeroenwijering.player.Model; 
     9import com.jeroenwijering.utils.Stretcher; 
     10 
     11import flash.display.Sprite; 
    912 
    1013 
    11 public class AbstractModel { 
     14public class AbstractModel extends Sprite { 
    1215 
    1316 
     
    2831        public function AbstractModel(mod:Model):void { 
    2932                model = mod; 
     33                mouseEnabled = false; 
    3034        }; 
    3135 
     
    4852        /** Resume playback of the item. **/ 
    4953        public function play():void {}; 
     54 
     55 
     56        /** Handle a resize of the display. **/ 
     57        public function resize():void { 
     58                Stretcher.stretch(this, 
     59                        model.config['width'], 
     60                        model.config['height'], 
     61                        model.config['stretching'] 
     62                ); 
     63        }; 
    5064 
    5165 
  • trunk/as3/com/jeroenwijering/models/HTTPModel.as

    r354 r374  
    1919 
    2020 
     21        /** Offset in bytes of the last seek. **/ 
     22        private var byteoffset:Number = 0; 
     23        /** Save if the bandwidth checkin already occurs. **/ 
     24        private var bwcheck:Boolean; 
     25        /** Switch on startup if the bandwidth is not enough. **/ 
     26        private var bwswitch:Boolean = true; 
    2127        /** NetConnection object for setup of the video stream. **/ 
    2228        private var connection:NetConnection; 
    23         /** NetStream instance that handles the stream IO. **/ 
    24         private var stream:NetStream; 
    25         /** Video object to be instantiated. **/ 
    26         private var video:Video; 
    27         /** Sound control object. **/ 
    28         private var transform:SoundTransform; 
    2929        /** ID for the position interval. **/ 
    3030        private var interval:Number; 
     31        /** Object with keyframe times and positions. **/ 
     32        private var keyframes:Object; 
    3133        /** Interval ID for the loading. **/ 
    3234        private var loadinterval:Number; 
    3335        /** Save whether metadata has already been sent. **/ 
    3436        private var meta:Boolean; 
    35         /** Object with keyframe times and positions. **/ 
    36         private var keyframes:Object; 
    37         /** Offset in bytes of the last seek. **/ 
    38         private var byteoffset:Number; 
    39         /** Offset in seconds of the last seek. **/ 
    40         private var timeoffset:Number; 
    4137        /** Boolean for mp4 / flv streaming. **/ 
    4238        private var mp4:Boolean; 
    43         /** Load offset for bandwidth checking. **/ 
    44         private var loadtimer:Number; 
    45         /** Variable that takes reloading into account. **/ 
    46         private var iterator:Number; 
    4739        /** Start parameter. **/ 
    4840        private var startparam:String = 'start'; 
     41        /** NetStream instance that handles the stream IO. **/ 
     42        private var stream:NetStream; 
     43        /** Offset in seconds of the last seek. **/ 
     44        private var timeoffset:Number = 0; 
     45        /** Sound control object. **/ 
     46        private var transformer:SoundTransform; 
     47        /** Video object to be instantiated. **/ 
     48        private var video:Video; 
    4949 
    5050 
     
    6161                stream.bufferTime = model.config['bufferlength']; 
    6262                stream.client = new NetClient(this); 
     63                transformer = new SoundTransform(); 
    6364                video = new Video(320,240); 
    6465                video.smoothing = model.config['smoothing']; 
    6566                video.attachNetStream(stream); 
    66                 transform = new SoundTransform(); 
    67                 byteoffset = timeoffset = 0; 
     67                addChild(video); 
    6868        }; 
    6969 
     
    8989 
    9090 
     91        /** Bandwidth is checked every four seconds as long as there's loading. **/ 
     92        private function getBandwidth(old:Number):void { 
     93                var ldd:Number = stream.bytesLoaded; 
     94                var bdw:Number = Math.round((ldd-old)*4/1000); 
     95                if(ldd < stream.bytesTotal) { 
     96                        if(bdw > 0) { model.config['bandwidth'] = bdw; } 
     97                        if(bwswitch) { 
     98                                bwswitch = false; 
     99                                if(getLevel() != model.config['level']) { 
     100                                        byteoffset = -1; 
     101                                        seek(position); 
     102                                        return; 
     103                                } 
     104                        } 
     105                        setTimeout(getBandwidth,2000,ldd); 
     106                } 
     107        }; 
     108 
     109 
     110        /** Return which level best fits the display width and connection bandwidth. **/ 
     111        private function getLevel():Number { 
     112                var lvl:Number = item['levels'].length-1; 
     113                for (var i:Number=0; i<item['levels'].length; i++) { 
     114                        if(model.config['width'] >= item['levels'][i].width &&  
     115                                model.config['bandwidth'] >= item['levels'][i].bitrate) { 
     116                                lvl = i; 
     117                                break; 
     118                        } 
     119                } 
     120                return lvl; 
     121        }; 
     122 
     123 
    91124        /** Return a keyframe byteoffset or timeoffset. **/ 
    92125        private function getOffset(pos:Number,tme:Boolean=false):Number { 
     
    115148                } 
    116149                if(item['streamer']) { 
    117                         url = item['streamer']; 
    118                         url = getURLConcat(url,'file',item['file']); 
     150                        if(item['streamer'].indexOf('/') > 0) { 
     151                                url = item['streamer']; 
     152                                url = getURLConcat(url,'file',item['file']); 
     153                        } else {  
     154                                startparam = item['streamer']; 
     155                        } 
    119156                } 
    120157                if(mp4) { 
     
    147184                item = itm; 
    148185                position = timeoffset; 
    149                 model.mediaHandler(video); 
     186                bwcheck = false; 
     187                if(item['levels']) { 
     188                        model.config['level'] = getLevel(); 
     189                        item['file'] = item['levels'][model.config['level']].url; 
     190                } 
    150191                stream.play(getURL()); 
    151                 iterator = 0; 
    152192                clearInterval(interval); 
    153193                interval = setInterval(positionInterval,100); 
     
    155195                loadinterval = setInterval(loadHandler,200); 
    156196                model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    157                 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 
    158197                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    159198        }; 
     
    171210                        clearInterval(loadinterval); 
    172211                } 
    173                 if(!loadtimer) { 
    174                         loadtimer = setTimeout(loadTimeout,3000); 
    175                 } 
    176         }; 
    177  
    178  
    179         /** timeout for checking the bitrate. **/ 
    180         private function loadTimeout():void { 
    181                 var obj:Object = new Object(); 
    182                 obj['bandwidth'] = Math.round(stream.bytesLoaded/1024/3*8); 
    183                 if(item['duration']) { 
    184                         obj['bitrate'] = Math.round(stream.bytesTotal/1024*8/item['duration']); 
    185                 } 
    186                 model.sendEvent('META',obj); 
     212                if(ldd > 0 && !bwcheck) { 
     213                        bwcheck = true; 
     214                        setTimeout(getBandwidth,2000,ldd); 
     215                } 
    187216        }; 
    188217 
    189218 
    190219        /** Get metadata information from netstream class. **/ 
    191         public function onData(dat:Object):void { 
     220        public function onClientData(dat:Object):void { 
    192221                if(dat.width) { 
    193222                        video.width = dat.width; 
    194223                        video.height = dat.height; 
     224                        super.resize(); 
     225                } 
     226                if(!item['duration'] && dat.duration) { 
     227                        item['duration'] = dat.duration; 
    195228                } 
    196229                if(dat['type'] == 'metadata' && !meta) { 
     
    229262        /** Interval for the position progress **/ 
    230263        private function positionInterval():void { 
    231                 iterator++; 
    232                 if(iterator > 10) { 
    233                         position = Math.round(stream.time*10)/10; 
    234                         if (mp4) { 
    235                                 position += timeoffset; 
    236                         } 
    237                 } 
    238                 var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100); 
    239                 if(bfr < 95 && position < Math.abs(item['duration']-stream.bufferTime-1)) { 
    240                         model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 
    241                         if(model.config['state'] != ModelStates.BUFFERING && bfr < 25) { 
    242                                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    243                         } 
    244                 } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) { 
     264                var pos:Number = Math.round(stream.time*10)/10; 
     265                if(pos > position - timeoffset + 5) { 
     266                        pos = position - timeoffset + 0.1; 
     267                } 
     268                if (mp4) { 
     269                        pos += timeoffset; 
     270                } 
     271                var bfr:Number = stream.bufferLength/stream.bufferTime; 
     272                if(bfr < 0.5 && pos < item['duration']-5 && model.config['state'] != ModelStates.BUFFERING) { 
     273                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
     274                } else if (bfr > 1 && model.config['state'] != ModelStates.PLAYING) { 
    245275                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
    246276                } 
    247                 if(position < item['duration'] + 10) { 
    248                         model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration']}); 
     277                if(pos < item['duration'] + 10) { 
     278                        if(pos != position) { 
     279                                model.sendEvent(ModelEvent.TIME,{position:pos,duration:item['duration']}); 
     280                                position = pos; 
     281                        } 
    249282                } else if (item['duration'] > 0) { 
    250283                        stream.pause(); 
    251284                        clearInterval(interval); 
    252285                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 
     286                } 
     287        }; 
     288 
     289 
     290        /** The stage has been resize. **/ 
     291        override public function resize():void { 
     292                super.resize(); 
     293                if(item['levels'] && getLevel() != model.config['level']) { 
     294                        byteoffset = getOffset(position); 
     295                        timeoffset = position = getOffset(position,true); 
     296                        load(item); 
    253297                } 
    254298        }; 
     
    301345                if(stream.bytesLoaded+byteoffset < stream.bytesTotal) { 
    302346                        stream.close(); 
    303                 } else {  
     347                } else { 
    304348                        stream.pause(); 
    305349                } 
     
    313357 
    314358 
    315         /** Set the volume level. **/ 
     359        /** Set the volume. **/ 
    316360        override public function volume(vol:Number):void { 
    317                 transform.volume = vol/100; 
    318                 stream.soundTransform = transform; 
     361                transformer.volume = vol/100; 
     362                stream.soundTransform = transformer; 
    319363        }; 
    320364 
  • trunk/as3/com/jeroenwijering/models/ImageModel.as

    r169 r374  
    3232                loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler); 
    3333                loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
     34                addChild(loader); 
    3435        }; 
    3536 
     
    5455        /** Load and place the image on stage. **/ 
    5556        private function loaderHandler(evt:Event):void { 
    56                 model.mediaHandler(loader); 
    5757                try { 
    5858                        Bitmap(loader.content).smoothing = true; 
    5959                } catch (err:Error) {} 
    6060                model.sendEvent(ModelEvent.META,{height:evt.target.height,width:evt.target.width}); 
     61                resize(); 
    6162                play(); 
    6263        }; 
  • trunk/as3/com/jeroenwijering/models/LivestreamModel.as

    r342 r374  
    88import com.jeroenwijering.models.AbstractModel; 
    99import com.jeroenwijering.player.Model; 
    10 import com.jeroenwijering.utils.Logger; 
    1110 
    1211import flash.display.*; 
     
    2120        /** URL of the livestream SWF. **/ 
    2221        private const LOCATION:String = "http://cdn.livestream.com/chromelessPlayer/wrappers/SimpleWrapper.swf"; 
    23         /** Testing key for developer.longtailvideo.com. **/ 
    24         private var key:String = '8Y5Rp-6ikHTF0DaOYmxqBWNv8mAx7FdRjvbf2Kk-xWkAG0JUKJwrfGmnsgDfUlNMHqQUmpBOho4cmCyMKDT41I_H3riecIRlu9f1DNBkwF_We7mGBy3CD1fKSAbltsIn'; 
     22 
    2523 
    2624        /** Loader for loading the Livestream API. **/ 
     
    3533        public function LivestreamModel(mod:Model):void { 
    3634                super(mod); 
     35                mouseEnabled = true; 
    3736                Security.allowDomain('*'); 
    3837                loader = new Loader(); 
    3938                loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderHandler); 
    4039                loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
     40                addChild(loader); 
    4141        }; 
    4242 
     
    4444        private function applicationHandler(evt:Event):void { 
    4545                wrapper = Object(loader.content).application; 
    46                 Logger.log('wrapper loaded: '+wrapper); 
    4746                wrapper.addEventListener("ready", playerReadyHandler); 
    4847        }; 
     
    5655 
    5756 
    58         /** Load the YouTube movie. **/ 
     57        /** Load the Livestream channel. **/ 
    5958        override public function load(itm:Object):void { 
    6059                item = itm; 
    6160                position = item['start']; 
    62                 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 
    6361                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    6462                if(player) { 
    6563                        play(); 
    6664                } else { 
     65                        Security.loadPolicyFile("http://cdn.livestream.com/crossdomain.xml"); 
    6766                        loader.load(new URLRequest(LOCATION),new LoaderContext(true, 
    6867                                ApplicationDomain.currentDomain,SecurityDomain.currentDomain)); 
     
    7372        /** Livestream player SWF loaded. **/ 
    7473        private function loaderHandler(evt:Event):void { 
    75                 Logger.log('swf loaded: '+loader.content); 
    7674                loader.content.addEventListener('applicationComplete',applicationHandler); 
    77         }; 
    78  
    79  
    80         /** Pause the YouTube movie. **/ 
    81         override public function pause():void { 
    82                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 
    8375        }; 
    8476 
     
    9587        /** Chromeless player has succesfully loaded. **/ 
    9688        private function playerReadyHandler(evt:Event):void { 
    97                 Logger.log('player loaded: '+wrapper.getPlayer()); 
    9889                player = wrapper.getPlayer(); 
    99                 model.mediaHandler(player as DisplayObject); 
    10090                player.addEventListener("errorEvent", playerErrorHandler); 
    101                 if(model.config['livestream.key']) { 
    102                         player.devKey = model.config['livestream.key']; 
    103                 } else { 
    104                         player.devKey = key; 
    105                 } 
     91                player.devKey = model.config['livestream.devkey']; 
    10692                player.showMuteButton = false; 
    10793                player.showPauseButton = false; 
     
    11096                player.volumeOverlayEnabled = true; 
    11197                player.volume = model.config['volume']/100; 
     98                resize(); 
    11299                play(); 
    113100        }; 
     
    119106                var msg:String = Object(evt).message; 
    120107                model.sendEvent(ModelEvent.ERROR,{message:msg}); 
    121         }; 
    122  
    123  
    124         /** Seek to position. **/ 
    125         override public function seek(pos:Number):void { 
    126                 position = pos; 
    127                 play(); 
    128108        }; 
    129109 
  • trunk/as3/com/jeroenwijering/models/RTMPModel.as

    r354 r374  
    2222 
    2323 
     24        /** Save if the bandwidth checkin already occurs. **/ 
     25        private var bwcheck:Boolean; 
     26        /** Switch if the bandwidth is not enough. **/ 
     27        private var bwswitch:Boolean = true; 
    2428        /** NetConnection object for setup of the video stream. **/ 
    2529        private var connection:NetConnection; 
     
    3034        /** NetStream instance that handles the stream IO. **/ 
    3135        private var stream:NetStream; 
     36        /** Offset in seconds of the last seek. **/ 
     37        private var timeoffset:Number = 0; 
    3238        /** Sound control object. **/ 
    33         private var transform:SoundTransform; 
     39        private var transformer:SoundTransform; 
    3440        /** Save the location of the XML redirect. **/ 
    3541        private var smil:String; 
    36         /** Save that the video has been started. **/ 
    37         private var started:Boolean; 
    38         /** Save that a file is unpublished. **/ 
    39         private var unpublished:Boolean; 
     42        /** Save that a stream is streaming. **/ 
     43        private var streaming:Boolean; 
    4044        /** Video object to be instantiated. **/ 
    4145        private var video:Video; 
     
    5155                connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    5256                connection.objectEncoding = ObjectEncoding.AMF0; 
    53                 connection.client = new Object(); 
     57                connection.client = new NetClient(this); 
    5458                loader = new URLLoader(); 
    5559                loader.addEventListener(Event.COMPLETE, loaderHandler); 
    5660                loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 
    5761                loader.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
     62                transformer = new SoundTransform(); 
    5863                video = new Video(320,240); 
    5964                video.smoothing = model.config['smoothing']; 
    60                 transform = new SoundTransform(); 
     65                addChild(video); 
    6166        }; 
    6267 
     
    6974 
    7075 
     76        /** Bandwidth is checked every four seconds as long as there's loading. **/ 
     77        private function getBandwidth():void { 
     78                if(streaming) { 
     79                        connection.call("checkBandwidth",null); 
     80                } 
     81        }; 
     82 
     83 
    7184        /** Extract the correct rtmp syntax from the file string. **/ 
    7285        private function getID(url:String):String { 
    7386                var ext:String = url.substr(-4); 
    74                 if(ext == '.mp3') { 
     87                if(model.config['rtmp.prepend'] == false) { 
     88                        return url; 
     89                } else if(ext == '.mp3') { 
    7590                        return 'mp3:'+url.substr(0,url.length-4); 
    76                 } else if(ext == '.mp4' || ext == '.mov' || ext == '.aac' || ext == '.m4a' || ext == '.f4v') { 
     91                } else if (ext=='.mp4' || ext=='.mov' || ext=='.m4v' || ext=='.aac' || ext=='.m4a' || ext=='.f4v') { 
    7792                        return 'mp4:'+url; 
    7893                } else if (ext == '.flv') { 
     
    8499 
    85100 
     101        /** Return which level best fits the display width and connection bandwidth. **/ 
     102        private function getLevel():Number { 
     103                var lvl:Number = item['levels'].length-1; 
     104                for (var i:Number=0; i<item['levels'].length; i++) { 
     105                        if(model.config['width'] >= item['levels'][i].width &&  
     106                                model.config['bandwidth'] >= item['levels'][i].bitrate) { 
     107                                lvl = i; 
     108                                break; 
     109                        } 
     110                } 
     111                return lvl; 
     112        }; 
     113 
     114 
    86115        /** Load content. **/ 
    87116        override public function load(itm:Object):void { 
    88117                item = itm; 
    89118                position = 0; 
    90                 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 
     119                timeoffset = item['start']; 
    91120                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    92121                if(model.config['rtmp.loadbalance']) { 
     
    94123                        loader.load(new URLRequest(smil)); 
    95124                } else { 
    96                         model.mediaHandler(video); 
    97125                        connection.connect(item['streamer']); 
    98126                } 
     
    105133                item['streamer'] = xml.children()[0].children()[0].@base.toString(); 
    106134                item['file'] = xml.children()[1].children()[0].@src.toString(); 
    107                 model.mediaHandler(video); 
    108135                connection.connect(item['streamer']); 
    109136        }; 
     
    111138 
    112139        /** Get metadata information from netstream class. **/ 
    113         public function onData(dat:Object):void { 
     140        public function onClientData(dat:Object):void { 
    114141                if(dat.width) { 
    115142                        video.width = dat.width; 
    116143                        video.height = dat.height; 
     144                        super.resize(); 
     145                        model.sendEvent(ModelEvent.META,dat); 
     146                } 
     147                if(dat.duration && !item['duration']) { 
     148                        item['duration'] = dat.duration; 
    117149                } 
    118150                if(dat.type == 'complete') { 
     
    123155                        stop(); 
    124156                } 
    125                 model.sendEvent(ModelEvent.META,dat); 
     157                if(dat.type == 'bandwidth') { 
     158                        model.config['bandwidth'] = dat.bandwidth; 
     159                        if(item['levels']) { 
     160                                if(!streaming) { 
     161                                        setStream(); 
     162                                } 
     163                                setTimeout(getBandwidth,10000); 
     164                        } 
     165                } 
    126166        }; 
    127167 
     
    132172                clearInterval(interval); 
    133173                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 
    134                 if(started && item['duration'] == 0) { 
    135                         stop(); 
    136                 } 
     174                if(stream && item['duration'] == 0) { stop(); } 
    137175        }; 
    138176 
     
    148186        /** Interval for the position progress. **/ 
    149187        private function positionInterval():void { 
    150                 position = Math.round(stream.time*10)/10; 
    151                 var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100); 
    152                 if(bfr < 95 && position < Math.abs(item['duration']-stream.bufferTime-1)) { 
    153                         model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 
    154                         if(model.config['state'] != ModelStates.BUFFERING && bfr < 20) { 
    155                                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    156                                 stream.bufferTime = model.config['bufferlength']; 
    157                                 model.sendEvent(ModelEvent.META,{bufferlength:model.config['bufferlength']}); 
    158                         } 
    159                 } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) { 
     188                var pos:Number = Math.round((stream.time+timeoffset)*10)/10; 
     189                var bfr:Number = stream.bufferLength/stream.bufferTime; 
     190                if(bfr < 0.5 && pos < item['duration']-5 && model.config['state'] != ModelStates.BUFFERING) { 
     191                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
     192                        stream.bufferTime = model.config['bufferlength']; 
     193                } else if (bfr > 1 && model.config['state'] != ModelStates.PLAYING) { 
    160194                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
    161195                        stream.bufferTime = model.config['bufferlength']*4; 
    162                         model.sendEvent(ModelEvent.META,{bufferlength:model.config['bufferlength']*4}); 
    163                 } 
    164                 if(position < item['duration']) { 
    165                         model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration']}); 
     196                } 
     197                if(pos < item['duration']) { 
     198                        if(pos != position) { 
     199                                model.sendEvent(ModelEvent.TIME,{position:pos,duration:item['duration']}); 
     200                                position = pos; 
     201                        } 
    166202                } else if (!isNaN(position) && item['duration'] > 0) { 
    167203                        stream.pause(); 
    168204                        clearInterval(interval); 
    169                         if(started && item['duration'] == 0) { stop(); } 
     205                        if(stream && item['duration'] == 0) { stop(); } 
    170206                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 
     207                } 
     208        }; 
     209 
     210 
     211        /** Check if the level must be switched on resize. **/ 
     212        override public function resize():void { 
     213                super.resize(); 
     214                if(getLevel() != model.config['level']) { 
     215                        seek( position); 
    171216                } 
    172217        }; 
     
    175220        /** Seek to a new position. **/ 
    176221        override public function seek(pos:Number):void { 
    177                 position = pos; 
     222                position = 0; 
     223                timeoffset = pos; 
    178224                clearInterval(interval); 
    179                 if(model.config['state'] != ModelStates.PLAYING) { 
     225                interval = setInterval(positionInterval,100); 
     226                if(item['levels'] && getLevel() != model.config['level']) { 
     227                        model.config['level'] = getLevel(); 
     228                        item['file'] = item['levels'][model.config['level']].url; 
     229                } 
     230                if(model.config['state'] == ModelStates.PAUSED) { 
    180231                        stream.resume(); 
    181232                } 
    182                 interval = setInterval(positionInterval,100); 
    183                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
    184                 stream.seek(position); 
     233                stream.play(getID(item['file']),timeoffset); 
     234                /*stream.play2({ 
     235                        streamName:getID(item['file']), 
     236                        start:timeoffset, 
     237                        transition:'reset' 
     238                });*/ 
     239                streaming = true; 
    185240        }; 
    186241 
     
    197252                video.attachNetStream(stream); 
    198253                model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    199                 interval = setInterval(positionInterval,100); 
    200                 stream.play(getID(item['file'])); 
     254                seek(timeoffset); 
    201255        }; 
    202256 
     
    210264                                                TEA.decrypt(evt.info.secureToken,model.config['token'])); 
    211265                                } 
    212                                 setStream(); 
     266                                if(!item['levels']) { setStream(); } 
     267                                connection.call("checkBandwidth",null); 
    213268                                var res:Responder = new Responder(streamlengthHandler); 
    214269                                connection.call("getStreamLength",res,getID(item['file'])); 
    215                                 connection.call("checkBandwidth",null); 
    216                                 break; 
    217                         case  'NetStream.Play.Start': 
    218                                 if(item['start'] > 0 && !started) { seek(item['start']); } 
    219                                 started = true; 
    220270                                break; 
    221271                        case  'NetStream.Seek.Notify': 
     
    234284                                        var msg:String = evt.info.code; 
    235285                                        if(evt.info['description']) { msg = evt.info['description']; } 
     286                                        stop(); 
    236287                                        model.sendEvent(ModelEvent.ERROR,{message:msg}); 
    237288                                } 
     
    239290                        case 'NetStream.Failed': 
    240291                        case 'NetStream.Play.StreamNotFound': 
    241                                 if(unpublished) { 
    242                                         onData({type:'complete'}); 
    243                                         unpublished = false; 
     292                                if(!streaming) { 
     293                                        onClientData({type:'complete'}); 
    244294                                } else {  
    245295                                        stop(); 
     
    252302                                break; 
    253303                        case 'NetStream.Play.UnpublishNotify': 
    254                                 unpublished = true; 
    255                                 break; 
    256                 } 
    257                 model.sendEvent(ModelEvent.META,evt.info); 
     304                                streaming = false; 
     305                                break; 
     306                } 
     307                model.sendEvent('META',evt.info); 
    258308        }; 
    259309 
     
    261311        /** Destroy the stream. **/ 
    262312        override public function stop():void { 
    263                 if(stream) {  
    264                         stream.close(); 
    265                 } 
     313                if(stream.time) { stream.close(); } 
     314                streaming = false; 
    266315                connection.close(); 
    267                 started = false; 
    268316                clearInterval(interval); 
    269317                position = 0; 
     318                timeoffset = item['start']; 
    270319                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE}); 
    271320                if(smil) {  
     
    277326        /** Get the streamlength returned from the connection. **/ 
    278327        private function streamlengthHandler(len:Number):void { 
    279                 if(len > 0) { onData({type:'streamlength',duration:len}); } 
     328                if(len && !item['duration']) { item['duration'] = len; } 
    280329        }; 
    281330 
     
    283332        /** Set the volume level. **/ 
    284333        override public function volume(vol:Number):void { 
    285                 transform.volume = vol/100; 
    286                 if(stream) {  
    287                         stream.soundTransform = transform; 
     334                transformer.volume = vol/100; 
     335                if(stream) { 
     336                        stream.soundTransform = transformer; 
    288337                } 
    289338        }; 
  • trunk/as3/com/jeroenwijering/models/SmoothModel.as

    r355 r374  
    99import com.jeroenwijering.parsers.SmoothParser; 
    1010import com.jeroenwijering.player.Model; 
     11import com.jeroenwijering.utils.Logger; 
    1112 
    12 import flash.display.Sprite; 
    1313import flash.events.*; 
    1414import flash.media.*; 
     
    2222        /** Currently playing chunk. **/ 
    2323        private var chunk:Number; 
    24         /** Chunk that is up next. **/ 
    25         private var next:Number; 
    2624        /** All available video chunks. **/ 
    2725        private var chunks:Array; 
    28         /** Container that switches the two video objects. **/ 
    29         private var container:Sprite; 
    3026        /** Index metadata of the stream. **/ 
    3127        private var index:Object; 
    3228        /** ID for the position interval. **/ 
    3329        private var interval:Number; 
    34         /** Currently active level. **/ 
    35         private var level:Number = 0; 
    36         /** All available quality levels. **/ 
    37         private var levels:Array; 
    3830        /** Loader that loads the manifest XML file. **/ 
    3931        private var loader:URLLoader; 
    4032        /** Soundtransform object. **/ 
    41         private var transform:SoundTransform; 
     33        private var transformer:SoundTransform; 
    4234 
    4335 
     
    4537        public function SmoothModel(mod:Model):void { 
    4638                super(mod); 
    47                 container = new Sprite(); 
    48                 container.graphics.drawRect(0,0,320,240); 
    4939                loader = new URLLoader(); 
    5040                loader.addEventListener(Event.COMPLETE, loaderHandler); 
    5141                loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 
    5242                loader.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
    53                 transform = new SoundTransform(); 
     43                transformer = new SoundTransform(); 
    5444        }; 
    5545 
     
    6252 
    6353 
     54 
    6455        /** Load content. **/ 
    6556        override public function load(itm:Object):void { 
    6657                item = itm; 
    67                 level = 0; 
    6858                chunk = 0; 
    6959                position = item['start']; 
    7060                if(model.config['mute']) { 
    71                          transform.volume = 0; 
     61                         transformer.volume = 0; 
    7262                } else {  
    73                          transform.volume = model.config['volume']/100; 
     63                         transformer.volume = model.config['volume']/100; 
    7464                } 
    7565                loader.load(new URLRequest(item['file'])); 
    76                 model.mediaHandler(container); 
    77                 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 
    7866                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    7967        }; 
     
    8169 
    8270        /** Load a chunk for playback. **/ 
    83         private function loadChunk(chk:Number):void { 
    84                 //var url:String = item['file'].substr(0,item['file'].length-3)+'mp4'; 
    85                 var url:String = 'http://h264.code-shop.com:8080/ccc.mp4'; 
    86                 url += '?start='+chunks[chk]['start']; 
    87                 url += '&end='+chunks[chk]['end']; 
    88                 chunks[chk].connection = new NetConnection(); 
    89                 chunks[chk].connection.connect(null); 
    90                 chunks[chk].netstream = new NetStream(chunks[chk].connection); 
    91                 chunks[chk].netstream.client = new Object(); 
    92                 chunks[chk].netstream.soundTransform = transform; 
    93                 chunks[chk].netstream.play(url); 
    94                 chunks[chk].netstream.pause(); 
    95                 chunks[chk].video = new Video(320,240); 
    96                 chunks[chk].video.smoothing = model.config['smoothing']; 
    97                 chunks[chk].video.visible = false; 
    98                 chunks[chk].video.attachNetStream(chunks[chk].netstream); 
    99                 container.addChild(chunks[chk].video); 
    100                 next = chk; 
    101         }; 
    102  
    103  
    104         /** Start playing a chunk. **/ 
    105         private function playChunk(chk:Number=0):void { 
    106                 chunks[chk].netstream.resume(); 
    107                 chunks[chk].video.visible = true; 
    108                 chunk = chk; 
    109         }; 
    110  
    111  
    112         /** Remove the current chunk. **/ 
    113         private function killChunk(chk:Number):void { 
    114                 if(chunks[chk] && chunks[chk].netstream) { 
    115                         chunks[chk].netstream.close(); 
     71        private function loadChunk(chk:Number,pse:Boolean=true):void { 
     72                var url:String = item['file'].substr(0,item['file'].length-5); 
     73                if(chunks[chk]) { 
     74                        url += '_' + item['levels'][0].bitrate + '.mp4'; 
     75                        url += '?start=' + chunks[chk]['start']; 
     76                        url += '&end=' + chunks[chk]['end']; 
     77                        chunks[chk].connection = new NetConnection(); 
     78                        chunks[chk].connection.connect(null); 
     79                        chunks[chk].netstream = new NetStream(chunks[chk].connection); 
     80                        chunks[chk].netstream.client = new Object(); 
     81                        chunks[chk].netstream.soundTransform = transformer; 
     82                        chunks[chk].netstream.play(url); 
     83                        chunks[chk].netstream.pause(); 
     84                        chunks[chk].netstream.seek(0); 
     85                        chunks[chk].video = new Video(); 
     86                        chunks[chk].video.width = 320; 
     87                        chunks[chk].video.height = 180; 
     88                        chunks[chk].video.attachNetStream(chunks[chk].netstream); 
    11689                } 
    11790        }; 
     
    12295                var xml:XML = XML(evt.target.data); 
    12396                index = SmoothParser.parseIndex(xml); 
    124                 model.sendEvent(ModelEvent.META,index); 
    125                 levels = SmoothParser.parseLevels(xml); 
     97                item['duration'] = index['duration']; 
     98                item['levels'] = SmoothParser.parseLevels(xml); 
    12699                chunks = SmoothParser.parseChunks(xml); 
    127                 if(levels.length == 0 || chunks.length == 0) { 
     100                if(item['levels'].length == 0 || chunks.length == 0) { 
    128101                        errorHandler(new ErrorEvent(ErrorEvent.ERROR,false,false, 
    129102                                "SmoothStreaming manifest contains no quality levels or chunks.")) 
    130103                } else { 
    131                         setLevel(); 
    132104                        seek(item['start']); 
    133105                } 
     
    151123 
    152124 
     125        /** Start playing a chunk. **/ 
     126        private function playChunk(chk:Number=0):void { 
     127                chunks[chk].netstream.resume(); 
     128                loadChunk(chk+1); 
     129                chunk = chk; 
     130                setTimeout(showChunk,100); 
     131        }; 
     132 
     133        private function showChunk() { 
     134                addChild(chunks[chunk].video); 
     135                resize(); 
     136        }; 
     137 
     138 
    153139        /** Interval for the position progress **/ 
    154140        private function positionInterval():void { 
    155                 var chk:Number = chunk; 
    156141                var obj:Object = chunks[chunk]; 
    157                 var pos:Number = obj['start']+obj.netstream.time; 
     142                position = obj['start']+obj.netstream.time; 
    158143                if(model.config['state'] != ModelStates.PLAYING) { 
    159144                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
    160145                } 
    161                 if(pos > obj['end']-0.15) { 
    162                         setTimeout(killChunk,2000,chk); 
    163                         playChunk(chk+1); 
    164                         setTimeout(loadChunk,1000,chk+2); 
     146                if(position >= obj.end-0.1) { 
     147                        playChunk(chunk+1); 
    165148                } 
    166                 if(pos < item['duration']) { 
    167                         pos = Math.round(pos*10)/10; 
    168                         if(pos != position) { 
    169                                 position = pos; 
    170                                 model.sendEvent(ModelEvent.TIME,{position:pos,duration:item['duration'],chunk:chk}); 
    171                         } 
     149                if(position < item['duration']) { 
     150                        model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration'],chunk:chunk}); 
    172151                } else if (item['duration'] > 0) { 
    173                         obj.netstream.pause(); 
    174152                        clearInterval(interval); 
    175153                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 
     
    182160                position = pos; 
    183161                clearInterval(interval); 
    184                 killChunk(chunk); 
    185                 killChunk(next); 
    186162                for (var i:Number=0; i<chunks.length; i++) { 
    187163                        if(chunks[i]['end'] > pos && chunks[i]['start'] <= pos) { 
    188164                                loadChunk(i); 
    189165                                playChunk(i); 
    190                                 setTimeout(loadChunk,1000,i+1); 
    191166                                break; 
    192167                        } 
     
    197172 
    198173 
    199         /** Set a specific stream level. **/ 
    200         private function setLevel():void { 
    201                 level = 0; 
    202                 model.sendEvent(ModelEvent.META,levels[level]); 
    203         }; 
    204  
    205  
    206174        /** Destroy the video. **/ 
    207175        override public function stop():void { 
    208                 killChunk(chunk); 
    209                 killChunk(next); 
    210176                clearInterval(interval); 
    211177                position = item['start']; 
     
    216182        /** Set the volume level. **/ 
    217183        override public function volume(vol:Number):void { 
    218                 transform.volume = vol/100; 
    219                 chunks[chunk].netstream.soundTransform = transform; 
     184                transformer.volume = vol/100; 
     185                chunks[chunk].netstream.soundTransform = transformer; 
    220186        }; 
    221187 
  • trunk/as3/com/jeroenwijering/models/SoundModel.as

    r210 r374  
    2121        private var sound:Sound; 
    2222        /** Sound control object. **/ 
    23         private var transform:SoundTransform; 
     23        private var transformer:SoundTransform; 
    2424        /** Sound channel object. **/ 
    2525        private var channel:SoundChannel; 
     
    3535        public function SoundModel(mod:Model):void { 
    3636                super(mod); 
    37                 transform = new SoundTransform(); 
     37                transformer = new SoundTransform(); 
    3838                context = new SoundLoaderContext(model.config['bufferlength']*1000,true); 
    3939        }; 
     
    9898                model.sendEvent(ModelEvent.LOADED,{loaded:ldd,total:ttl}); 
    9999                if(ldd/ttl > 0.1 && item['duration'] == 0) { 
    100                         model.sendEvent(ModelEvent.META,{duration:sound.length/1000/ldd*ttl}); 
     100                        item['duration'] =  sound.length/1000/ldd*ttl; 
    101101                } 
    102102                if(ldd == ttl && ldd > 0) { 
     
    116116        /** Play the sound. **/ 
    117117        override public function play():void { 
    118                 channel = sound.play(position*1000,0,transform); 
     118                channel = sound.play(position*1000,0,transformer); 
    119119                channel.addEventListener(Event.SOUND_COMPLETE,completeHandler); 
    120120                interval = setInterval(positionInterval,100); 
     
    167167        /** Set the volume level. **/ 
    168168        override public function volume(vol:Number):void { 
    169                 transform.volume = vol/100; 
     169                transformer.volume = vol/100; 
    170170                if(channel) { 
    171                         channel.soundTransform = transform; 
     171                        channel.soundTransform = transformer; 
    172172                } 
    173173        }; 
  • trunk/as3/com/jeroenwijering/models/VideoModel.as

    r354 r374  
    88import com.jeroenwijering.models.AbstractModel; 
    99import com.jeroenwijering.player.Model; 
    10 import com.jeroenwijering.utils.NetClient; 
     10import com.jeroenwijering.utils.*; 
    1111 
    1212import flash.events.*; 
     
    1919 
    2020 
     21        /** Save if the bandwidth checkin already occurs. **/ 
     22        private var bwcheck:Boolean; 
     23        /** Switch if the bandwidth is not enough. **/ 
     24        private var bwswitch:Boolean = true; 
     25        /** NetConnection object for setup of the video stream. **/ 
     26        private var connection:NetConnection; 
     27        /** ID for the position interval. **/ 
     28        private var interval:Number; 
     29        /** Interval ID for the loading. **/ 
     30        private var loading:Number; 
     31        /** NetStream instance that handles the stream IO. **/ 
     32        private var stream:NetStream; 
     33        /** Sound control object. **/ 
     34        private var transformer:SoundTransform; 
    2135        /** Video object to be instantiated. **/ 
    22         protected var video:Video; 
    23         /** NetConnection object for setup of the video stream. **/ 
    24         protected var connection:NetConnection; 
    25         /** NetStream instance that handles the stream IO. **/ 
    26         protected var stream:NetStream; 
    27         /** Sound control object. **/ 
    28         protected var transform:SoundTransform; 
    29         /** ID for the position interval. **/ 
    30         protected var interval:Number; 
    31         /** Interval ID for the loading. **/ 
    32         protected var loadinterval:Number; 
    33         /** Load offset for bandwidth checking. **/ 
    34         protected var loadtimer:Number; 
     36        private var video:Video; 
    3537 
    3638 
     
    4648                stream.bufferTime = model.config['bufferlength']; 
    4749                stream.client = new NetClient(this); 
     50                transformer = new SoundTransform(); 
    4851                video = new Video(320,240); 
    4952                video.smoothing = model.config['smoothing']; 
    5053                video.attachNetStream(stream); 
    51                 transform = new SoundTransform(); 
     54                addChild(video); 
    5255        }; 
    5356 
    5457 
    5558        /** Catch security errors. **/ 
    56         protected function errorHandler(evt:ErrorEvent):void { 
     59        private function errorHandler(evt:ErrorEvent):void { 
    5760                stop(); 
    5861                model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 
     62        }; 
     63 
     64 
     65        /** Bandwidth is checked every four seconds as long as there's loading. **/ 
     66        private function getBandwidth(old:Number):void { 
     67                var ldd:Number = stream.bytesLoaded; 
     68                var bdw:Number = Math.round((ldd-old)*4/1000); 
     69                if(ldd < stream.bytesTotal) { 
     70                        if(bdw > 0) { model.config['bandwidth'] = bdw; } 
     71                        if(bwswitch) { 
     72                                bwswitch = false; 
     73                                if(getLevel() != model.config['level']) { 
     74                                        model.config['level'] = getLevel(); 
     75                                        item['file'] = item['levels'][model.config['level']].url; 
     76                                        load(item); 
     77                                        return; 
     78                                } 
     79                        } 
     80                        setTimeout(getBandwidth,2000,ldd); 
     81                } 
     82        }; 
     83 
     84 
     85        /** Return which level best fits the display width and connection bandwidth. **/ 
     86        private function getLevel():Number { 
     87                var lvl:Number = item['levels'].length-1; 
     88                for (var i:Number=0; i<item['levels'].length; i++) { 
     89                        if(model.config['width'] >= item['levels'][i].width && 
     90                                model.config['bandwidth'] >= item['levels'][i].bitrate) { 
     91                                lvl = i; 
     92                                break; 
     93                        } 
     94                } 
     95                return lvl; 
    5996        }; 
    6097 
     
    64101                item = itm; 
    65102                position = 0; 
    66                 model.mediaHandler(video); 
     103                bwcheck = false; 
     104                if(item['levels']) { 
     105                        model.config['level'] = getLevel(); 
     106                        item['file'] = item['levels'][model.config['level']].url; 
     107                } 
    67108                stream.checkPolicyFile = true; 
    68109                stream.play(item['file']); 
     110                clearInterval(interval); 
    69111                interval = setInterval(positionInterval,100); 
    70                 loadinterval = setInterval(loadHandler,200); 
     112                clearInterval(loading); 
     113                loading = setInterval(loadHandler,200); 
    71114                model.config['mute'] == true ? volume(0): volume(model.config['volume']); 
    72                 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 
    73115                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    74116        }; 
     
    76118 
    77119        /** Interval for the loading progress **/ 
    78         protected function loadHandler():void { 
     120        private function loadHandler():void { 
    79121                var ldd:Number = stream.bytesLoaded; 
    80122                var ttl:Number = stream.bytesTotal; 
    81123                model.sendEvent(ModelEvent.LOADED,{loaded:ldd,total:ttl}); 
    82                 if(ldd == ttl && ldd > 0) { 
    83                         clearInterval(loadinterval); 
    84                 } 
    85                 if(!loadtimer) { 
    86                         loadtimer = setTimeout(loadTimeout,3000); 
    87                 } 
    88         }; 
    89  
    90  
    91         /** timeout for checking the bitrate. **/ 
    92         protected function loadTimeout():void { 
    93                 model.sendEvent('META',{ 
    94                         bandwidth:Math.round(stream.bytesLoaded/1024/3*8) 
    95                 }); 
     124                if(ldd && ldd == ttl) { 
     125                        clearInterval(loading); 
     126                } 
     127                if(ldd > 0 && !bwcheck) { 
     128                        bwcheck = true; 
     129                        setTimeout(getBandwidth,2000,ldd); 
     130                } 
    96131        }; 
    97132 
    98133 
    99134        /** Get metadata information from netstream class. **/ 
    100         public function onData(dat:Object):void { 
     135        public function onClientData(dat:Object):void { 
    101136                if(dat.width) { 
    102137                        video.width = dat.width; 
    103138                        video.height = dat.height; 
     139                        resize(); 
     140                } 
     141                if(dat.duration && !item['duration']) { 
     142                        item['duration'] = dat.duration; 
    104143                } 
    105144                model.sendEvent(ModelEvent.META,dat); 
     
    124163 
    125164        /** Interval for the position progress **/ 
    126         protected function positionInterval():void { 
    127                 position = Math.round(stream.time*10)/10; 
    128                 var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100); 
    129                 if(bfr < 95 && position < Math.abs(item['duration']-stream.bufferTime-1)) { 
    130                         model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 
    131                         if(model.config['state'] != ModelStates.BUFFERING && bfr < 25) { 
    132                                 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
     165        private function positionInterval():void { 
     166                var pos:Number = Math.round(stream.time*10)/10; 
     167                var bfr:Number = stream.bufferLength/stream.bufferTime; 
     168                if(bfr < 0.5 && position < item['duration']-5 && model.config['state'] != ModelStates.BUFFERING) { 
     169                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
     170                } else if (bfr > 1 && model.config['state'] != ModelStates.PLAYING) { 
     171                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
     172                } 
     173                if(pos < item['duration'] + 10) { 
     174                        if(pos != position) { 
     175                                position = pos; 
     176                                model.sendEvent(ModelEvent.TIME,{position:pos,duration:item['duration']}); 
    133177                        } 
    134                 } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) { 
    135                         model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 
    136                 } 
    137                 if(position < item['duration'] + 10) { 
    138                         model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration']}); 
    139178                } else if (item['duration']) { 
    140179                        stream.pause(); 
     
    155194 
    156195        /** Receive NetStream status updates. **/ 
    157         protected function statusHandler(evt:NetStatusEvent):void { 
     196        private function statusHandler(evt:NetStatusEvent):void { 
    158197                switch (evt.info.code) { 
    159198                        case "NetStream.Play.Stop": 
     
    179218                        stream.pause(); 
    180219                } 
    181                 loadtimer = undefined; 
    182                 clearInterval(loadinterval); 
     220                clearInterval(loading); 
    183221                clearInterval(interval); 
    184222                position = 0; 
     
    187225 
    188226 
    189         /** Set the volume level. **/ 
     227        /** Set the volume. **/ 
    190228        override public function volume(vol:Number):void { 
    191                 transform.volume = vol/100; 
    192                 stream.soundTransform = transform; 
     229                transformer.volume = vol/100; 
     230                stream.soundTransform = transformer; 
    193231        }; 
    194232 
  • trunk/as3/com/jeroenwijering/models/YoutubeModel.as

    r183 r374  
    88import com.jeroenwijering.models.AbstractModel; 
    99import com.jeroenwijering.player.Model; 
     10import com.jeroenwijering.utils.Logger; 
    1011 
    1112import flash.display.Loader; 
     
    1415import flash.net.URLRequest; 
    1516import flash.system.Security; 
     17import flash.utils.setTimeout; 
    1618 
    1719 
     
    2729        /** connection from the YT proxy. **/ 
    2830        private var inbound:LocalConnection; 
    29         /** Save that the meta has been sent. **/ 
    30         private var metasent:Boolean; 
    3131        /** Save that a load call has been sent. **/ 
    3232        private var loading:Boolean; 
    3333        /** Save the connection state. **/ 
    3434        private var connected:Boolean; 
    35         /** URL of a custom youtube swf. **/ 
    36         private var location:String; 
    3735 
    3836 
     
    4139                super(mod); 
    4240                Security.allowDomain('*'); 
    43                 var url:String = model.display.loaderInfo.url; 
    44                 if(url.indexOf('http://') == 0) { 
    45                         unique = Math.random().toString().substr(2); 
    46                         var str:String = url.substr(0,url.indexOf('.swf')); 
    47                         location = str.substr(0,str.lastIndexOf('/')+1)+'yt.swf?unique='+unique; 
    48                 } else { 
    49                         unique = '1'; 
    50                         location = 'yt.swf'; 
    51                 } 
    5241                outgoing = new LocalConnection(); 
    5342                outgoing.allowDomain('*'); 
     
    5847                inbound.allowInsecureDomain('*'); 
    5948                inbound.addEventListener(StatusEvent.STATUS,onLocalConnectionStatusChange); 
    60                 //inbound.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 
    6149                inbound.client = this; 
    6250                loader = new Loader(); 
    6351                loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 
     52                addChild(loader); 
    6453        }; 
    6554 
     
    8978 
    9079 
     80        /** Get the location of yt.swf. **/ 
     81        private function getLocation():String { 
     82                var loc:String; 
     83                var url:String = loaderInfo.url; 
     84                if(url.indexOf('http://') == 0) { 
     85                        unique = Math.random().toString().substr(2); 
     86                        loc = url.substr(0,url.indexOf('.swf')); 
     87                        loc = loc.substr(0,loc.lastIndexOf('/')+1)+'yt.swf?unique='+unique; 
     88                } else { 
     89                        unique = '1'; 
     90                        loc = 'yt.swf'; 
     91                } 
     92                return loc; 
     93        }; 
     94 
    9195        /** Load the YouTube movie. **/ 
    9296        override public function load(itm:Object):void { 
     
    97101                        if(outgoing) { 
    98102                                var gid = getID(item['file']); 
    99                                 resize(model.config['width'],model.config['width']/4*3); 
    100103                                outgoing.send('AS3_'+unique,"loadVideoById",gid,item['start']); 
    101                                 model.mediaHandler(loader); 
     104                                resize(); 
    102105                        } 
    103106                } else { 
     107                        loader.load(new URLRequest(getLocation())); 
    104108                        inbound.connect('AS2_'+unique); 
    105                         loader.load(new URLRequest(location)); 
    106                 } 
    107                 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 
     109                } 
    108110                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 
    109111        }; 
     
    134136 
    135137        /** error was thrown without this handler **/ 
    136         public function onLocalConnectionStatusChange(evt:StatusEvent):void { 
    137                 // model.sendEvent(ModelEvent.META,{status:evt.code}); 
    138         }; 
     138        public function onLocalConnectionStatusChange(evt:StatusEvent):void {}; 
    139139 
    140140 
    141141        /** Catch youtube errors. **/ 
    142         public function onError(erc:String):void { 
    143                 model.sendEvent(ModelEvent.ERROR,{message:"YouTube error (video not found?):\n"+item['file']}); 
     142        public function onError(erc:Number):void { 
    144143                stop(); 
     144                var msg:String = 'Video not found or deleted: ' + getID(item['file']); 
     145                if(erc == 101 || erc == 150) {  
     146                        msg = 'Embedding this video is disabled by its owner.'; 
     147                } 
     148                model.sendEvent(ModelEvent.ERROR,{message:msg}); 
    145149        }; 
    146150 
     
    149153        public function onStateChange(stt:Number):void { 
    150154                switch(Number(stt)) { 
    151                         case -1: 
    152                                 // model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE}); 
    153                                 break; 
    154155                        case 0: 
    155156                                if(model.config['state'] != ModelStates.BUFFERING && model.config['state'] != ModelStates.IDLE) { 
     
    180181        public function onTimeChange(pos:Number,dur:Number):void { 
    181182                model.sendEvent(ModelEvent.TIME,{position:pos,duration:dur}); 
    182                 if(!metasent) { 
    183                         model.sendEvent(ModelEvent.META,{width:320,height:240,duration:dur}); 
    184                         metasent = true; 
    185                 } 
     183                if(!item['duration']) { item['duration'] = dur; } 
     184                 
    186185        }; 
    187186 
    188187 
    189188        /** Resize the YT player. **/ 
    190         public function resize(wid:Number,hei:Number) { 
    191                 outgoing.send('AS3_'+unique,"setSize",wid,hei); 
     189        override public function resize():void { 
     190                outgoing.send('AS3_'+unique,"setSize",model.config['width'],model.config['height']); 
    192191        }; 
    193192 
     
    202201        /** Destroy the youtube video. **/ 
    203202        override public function stop():void { 
    204                 metasent = false; 
    205203                outgoing.send('AS3_'+unique,"stopVideo"); 
    206204                position = 0; 
  • trunk/as3/com/jeroenwijering/parsers/ASXParser.as

    r161 r374  
    66 
    77import com.jeroenwijering.parsers.JWParser; 
     8import com.jeroenwijering.parsers.MediaParser; 
    89import com.jeroenwijering.utils.Strings; 
    910 
     
    5657                        } 
    5758                } 
     59                itm = MediaParser.parseGroup(obj,itm); 
    5860                itm = JWParser.parseEntry(obj,itm); 
    5961                return itm; 
  • trunk/as3/com/jeroenwijering/parsers/MediaParser.as

    r211 r374  
    4242                                                        itm = MediaParser.parseGroup(i,itm); 
    4343                                                } 
     44                                                if(i.@width && i.@bitrate) { 
     45                                                        if(!itm.levels) { 
     46                                                                itm.levels = new Array(); 
     47                                                        } 
     48                                                        itm.levels.push({ 
     49                                                                width:i.@width.toString(), 
     50                                                                bitrate:i.@bitrate.toString(), 
     51                                                                url:i.@url.toString() 
     52                                                        }); 
     53                                                } 
    4454                                                break; 
    4555                                        case 'title': 
  • trunk/as3/com/jeroenwijering/parsers/SmoothParser.as

    r338 r374  
    4545                for each (var i:XML in dat.children()[0].children()) { 
    4646                        if (i.localName().toLowerCase() == 'qualitylevel') { 
    47                                 var obj:Object = new Object(); 
    48                                 for(var j:Number=0; j<i.@*.length(); j++) { 
    49                                         obj[i.@*[j].name().toString().toLowerCase()] = i.@*[j].toString(); 
    50                                 } 
     47                                var obj:Object = { 
     48                                        bitrate:Number(i.@Bitrate.toString())/1000, 
     49                                        width:Number(i.@Width.toString())/1, 
     50                                        height:Number(i.@Height.toString())/1 
     51                                }; 
    5152                                Logger.log(obj); 
    5253                                arr.push(obj); 
  • trunk/as3/com/jeroenwijering/parsers/XSPFParser.as

    r161 r374  
    66 
    77import com.jeroenwijering.parsers.JWParser; 
     8import com.jeroenwijering.parsers.MediaParser; 
    89import com.jeroenwijering.utils.Strings; 
    910 
     
    5859                        } 
    5960                } 
     61                itm = MediaParser.parseGroup(obj,itm); 
    6062                itm = JWParser.parseEntry(obj,itm); 
    6163                return itm; 
  • trunk/as3/com/jeroenwijering/player/Controller.as

    r354 r374  
    5555                'sdp':'video', 
    5656                'swf':'image', 
    57                 'vp6':'video', 
    58                 'smc':'smooth' 
     57                'vp6':'video' 
    5958        }; 
    6059        /** Elements of config that are part of the playlist. **/ 
     
    9998        public function closeMVC(mdl:Model,vie:View):void { 
    10099                model= mdl; 
    101                 model.addEventListener(ModelEvent.META,metaHandler); 
    102100                model.addEventListener(ModelEvent.STATE,stateHandler); 
    103101                view = vie; 
     
    136134        /** Set the fullscreen rectangle **/ 
    137135        private function fullscreenrect():void { 
    138                 var srx:Number = Capabilities.screenResolutionX; 
    139                 var asr:Number = srx/Capabilities.screenResolutionY; 
    140136                var pnt:Point = skin.parent.localToGlobal(new Point(skin.x,skin.y)); 
    141                 try { 
    142                         var wid:Number = playlist[config['item']]['width']; 
    143                 } catch (err:Error) {} 
    144                 if(wid && wid > srx) { 
    145                         skin.stage["fullScreenSourceRect"] = new Rectangle(pnt.x,pnt.y,srx,Capabilities.screenResolutionY); 
    146                 } else if(wid && wid > srx/2) { 
    147                         skin.stage["fullScreenSourceRect"] = new Rectangle(pnt.x,pnt.y,wid,Math.round(wid/asr)); 
    148                 } else { 
    149                         skin.stage["fullScreenSourceRect"] = new Rectangle(pnt.x,pnt.y,srx/2,Capabilities.screenResolutionY/2); 
    150                 } 
     137                skin.stage["fullScreenSourceRect"] = new Rectangle( 
     138                        pnt.x, 
     139                        pnt.y, 
     140                        Capabilities.screenResolutionX, 
     141                        Capabilities.screenResolutionY 
     142                ); 
    151143        }; 
    152144 
     
    274266 
    275267 
    276         /** Update playlist item duration. **/ 
    277         private function metaHandler(evt:ModelEvent):void { 
    278                 if(evt.data.duration && playlist[config['item']]['duration'] == 0) { 
    279                         playlist[config['item']]['duration'] = evt.data.duration; 
    280                 } 
    281                 if(evt.data.width) { 
    282                         playlist[config['item']]['width'] = evt.data.width; 
    283                         playlist[config['item']]['height'] = evt.data.height; 
    284                 } 
    285         }; 
    286  
    287  
    288268        /** Save new state of the mute switch and send volume. **/ 
    289269        private function muteHandler(evt:ViewEvent):void { 
     
    374354                if (config['item'] == 0) { 
    375355                        playItem(playlist.length-1); 
    376                 } else {  
     356                } else { 
    377357                        playItem(config['item']-1); 
    378358                } 
     
    385365                        var dps:String = skin.stage['displayState']; 
    386366                } catch (err:Error) {} 
    387                 if(dps == 'fullScreen' && config['resizing']) { 
     367                if(dps == 'fullScreen') { 
    388368                        config['fullscreen'] = true; 
    389369                        sploader.layoutFullscreen(); 
    390370                } else { 
    391                         if(config['resizing']) { 
    392                                 config['width'] = skin.stage.stageWidth; 
    393                                 config['height'] = skin.stage.stageHeight; 
    394                         } 
     371                        config['width'] = skin.stage.stageWidth; 
     372                        config['height'] = skin.stage.stageHeight; 
    395373                        config['fullscreen'] = false; 
    396374                        sploader.layoutNormal(); 
     
    431409        private function stateHandler(evt:ModelEvent):void { 
    432410                if(evt.data.newstate == ModelStates.COMPLETED) { 
    433                         if(config['oncomplete'] == 'link') {  
    434                                 linkHandler(); 
    435                         } 
    436411                        switch (config['repeat']) { 
    437412                                case 'single': 
  • trunk/as3/com/jeroenwijering/player/Model.as

    r331 r374  
    2121        /** Object with all configuration variables. **/ 
    2222        public var config:Object; 
    23         /** Reference to the display MovieClip. **/ 
    24         public var display:MovieClip; 
    25         /** Object with all display variables. **/ 
    26         private var sploader:SPLoader; 
     23        /** Reference to the media element. **/ 
     24        public var media:Sprite; 
    2725        /** Reference to the player's controller. **/ 
    2826        private var controller:Controller; 
     
    4038        public function Model(cfg:Object,skn:MovieClip,ldr:SPLoader,ctr:Controller):void { 
    4139                config = cfg; 
    42                 display = MovieClip(skn.getChildByName('display')); 
    43                 sploader = ldr; 
    4440                controller = ctr; 
    4541                controller.addEventListener(ControllerEvent.ITEM,itemHandler); 
     
    5147                controller.addEventListener(ControllerEvent.STOP,stopHandler); 
    5248                controller.addEventListener(ControllerEvent.VOLUME,volumeHandler); 
     49                models = new Object(); 
    5350                thumb = new Loader(); 
    5451                thumb.contentLoaderInfo.addEventListener(Event.COMPLETE,thumbHandler); 
    5552                thumb.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,thumbHandler); 
    56                 Draw.clear(display.media); 
    57                 display.addChildAt(thumb,display.getChildIndex(display.media)); 
    58                 display.media.visible = false; 
    59                 models = new Object(); 
     53                var dpl:MovieClip = skn.getChildByName('display') as MovieClip; 
     54                media = dpl.media as Sprite; 
     55                media.visible = false; 
     56                Draw.clear(media); 
     57                dpl.addChildAt(thumb,dpl.getChildIndex(media)); 
    6058        }; 
    6159 
     
    6664        }; 
    6765 
     66        /** Check if the currently playing item is audio only. **/ 
     67        private function audioOnly():Boolean { 
     68                var ext:String = item['file'].substr(-3); 
     69                if(ext == 'm4a' || ext == 'mp3' || ext == 'aac') { 
     70                        return true; 
     71                } else { 
     72                        return false; 
     73                } 
     74        }; 
     75 
    6876 
    6977        /** Item change: stop the old model and start the new one. **/ 
     
    7179                if(item) { 
    7280                        models[item['type']].stop(); 
     81                        media.removeChild(models[item['type']]); 
    7382                } 
    7483                item = controller.playlist[config['item']]; 
    7584                if(models[item['type']]) { 
     85                        media.addChild(models[item['type']]); 
    7686                        models[item['type']].load(item); 
    7787                } else { 
     
    90100 
    91101 
    92         /**  
    93         * Place the mediafile fro the current model on stage. 
    94         *  
    95         * @param obj    The displayobject (MovieClip/Video/Loader) to display. 
    96         **/ 
    97         public function mediaHandler(obj:DisplayObject=undefined):void { 
    98                 Draw.clear(display.media); 
    99                 display.media.addChild(obj); 
    100                 resizeHandler(); 
    101         }; 
    102  
    103  
    104102        /** Make the current model toggle its mute state. **/ 
    105103        private function muteHandler(evt:ControllerEvent):void { 
     
    119117                        if(evt.data.state == true) { 
    120118                                models[item['type']].play(); 
    121                         } else {  
     119                        } else { 
    122120                                models[item['type']].pause(); 
    123121                        } 
     
    126124 
    127125 
    128         /** Load a new thumbnail. **/ 
     126        /** Load a thumb; either from the playlist or (if there) player-wide. **/ 
    129127        private function playlistHandler(evt:ControllerEvent):void { 
    130128                var img:String = controller.playlist[config['item']]['image']; 
     
    137135 
    138136        /** Resize the media and thumb. **/ 
    139         private function resizeHandler(evt:Event=null):void { 
    140                 var wid:Number = sploader.getPlugin('display').config['width']; 
    141                 var hei:Number = sploader.getPlugin('display').config['height']; 
    142                 Stretcher.stretch(display.media,wid,hei,config['stretching']); 
    143                 if(thumb.width > 10 && wid > 10) { 
    144                         Stretcher.stretch(thumb,wid,hei,config['stretching']); 
    145                 } 
     137        private function resizeHandler(evt:ControllerEvent):void { 
     138                if(thumb.width) { thumbResize(); }; 
     139                if(item) { models[item['type']].resize(); } 
    146140        }; 
    147141 
     
    163157 
    164158 
    165         /**   
     159        /** 
    166160        * Dispatch events to the View/ Controller. 
    167161        * When switching states, the thumbnail is shown/hidden. 
     
    173167        public function sendEvent(typ:String,dat:Object):void { 
    174168                if(typ == ModelEvent.STATE) { 
    175                         if(dat.newstate == config['state']) { 
    176                                 return; 
    177                         } 
    178169                        dat['oldstate'] = config['state']; 
    179170                        config['state'] = dat.newstate; 
     
    182173                                        sendEvent(ModelEvent.LOADED,{loaded:0,offset:0,total:0}); 
    183174                                case ModelStates.COMPLETED: 
    184                                         if(config['oncomplete'] != 'none') { 
    185                                                 thumb.visible = true; 
    186                                                 display.media.visible = false; 
    187                                                 sendEvent(ModelEvent.TIME,{position:item['start'],duration:item['duration']}); 
    188                                         } 
     175                                        thumb.visible = true; 
     176                                        media.visible = false; 
     177                                        sendEvent(ModelEvent.TIME,{position:item['start'],duration:item['duration']}); 
    189178                                        break; 
    190179                                case ModelStates.PLAYING: 
    191                                         if(item['file'].substr(-3) == 'm4a' || 
    192                                                 item['file'].substr(-3) == 'mp3' || 
    193                                                 item['file'].substr(-3) == 'aac') { 
    194                                                 thumb.visible = true; 
    195                                                 display.media.visible = false; 
    196                                         } else {  
    197                                                 thumb.visible = false; 
    198                                                 display.media.visible = true; 
    199                                         } 
     180                                        thumb.visible = audioOnly(); 
     181                                        media.visible = !audioOnly(); 
    200182                                        break; 
    201183                        } 
    202                 } else if(dat.width) { 
    203                         resizeHandler(); 
    204184                } 
    205185                Logger.log(dat,typ); 
     
    213193                        Bitmap(thumb.content).smoothing = true; 
    214194                } catch (err:Error) {} 
    215                 resizeHandler(); 
     195                thumbResize(); 
     196        }; 
     197 
     198 
     199        /** Resize the thumbnail. **/ 
     200        private function thumbResize():void { 
     201                Stretcher.stretch(thumb,config['width'],config['height'],config['stretching']); 
    216202        }; 
    217203 
  • trunk/as3/com/jeroenwijering/player/Player.as

    r354 r374  
    4848 
    4949                autostart:false, 
     50                bandwidth:5000, 
    5051                bufferlength:1, 
    5152                displayclick:'play', 
    5253                fullscreen:false, 
    5354                item:0, 
     55                level:0, 
    5456                linktarget:'_blank', 
    5557                logo:undefined, 
    5658                mute:false, 
    57                 oncomplete:'rewind', 
    5859                repeat:'none', 
    59                 resizing:true, 
    6060                shuffle:false, 
    6161                smoothing:true, 
     
    7070                id:undefined, 
    7171                plugins:undefined, 
    72                 version:'4.6.535' 
     72                version:'4.6.374' 
    7373        }; 
    7474        /** Reference to all stage graphics. **/ 
     
    141141                model.addModel(new HTTPModel(model),'http'); 
    142142                model.addModel(new ImageModel(model),'image'); 
    143                 //model.addModel(new LivestreamModel(model),'livestream'); 
     143                model.addModel(new LivestreamModel(model),'livestream'); 
    144144                model.addModel(new RTMPModel(model),'rtmp'); 
    145145                model.addModel(new SmoothModel(model),'smooth'); 
  • trunk/as3/com/jeroenwijering/player/SPLoader.as

    r298 r374  
    264264                        plugins[overs[j]]['visible'] = true; 
    265265                } 
    266                 if(config['resizing']) { 
    267                         config['width'] = bounds.width; 
    268                         config['height'] = bounds.height; 
    269                 } 
     266                config['width'] = bounds.width; 
     267                config['height'] = bounds.height; 
    270268        }; 
    271269 
     
    285283                        } 
    286284                } 
    287                 if(config['resizing']) { 
    288                         config['width'] = skin.stage.stageWidth; 
    289                         config['height'] = skin.stage.stageHeight; 
    290                 } 
     285                config['width'] = skin.stage.stageWidth; 
     286                config['height'] = skin.stage.stageHeight; 
    291287        }; 
    292288 
  • trunk/as3/com/jeroenwijering/player/View.as

    r216 r374  
    4343                _config['client'] = 'FLASH '+Capabilities.version; 
    4444                _skin = skn; 
    45                 if(_config['resizing']) { 
    46                         _skin.stage.scaleMode = "noScale"; 
    47                         _skin.stage.align = "TL"; 
    48                         _skin.stage.addEventListener(Event.RESIZE,resizeHandler); 
    49                 } else { 
    50                         _skin.stage.addEventListener(FullScreenEvent.FULL_SCREEN,resizeHandler); 
    51                 } 
     45                _skin.stage.scaleMode = "noScale"; 
     46                _skin.stage.align = "TL"; 
     47                _skin.stage.addEventListener(Event.RESIZE,resizeHandler); 
    5248                sploader = ldr; 
    5349                controller = ctr; 
  • trunk/as3/com/jeroenwijering/plugins/Display.as

    r242 r374  
    6969                        clip.addEventListener(MouseEvent.CLICK,clickHandler); 
    7070                        clip.buttonMode = true; 
    71                         clip.mouseChildren = false; 
    7271                } 
    7372                if(clip.logo) { 
  • trunk/as3/com/jeroenwijering/plugins/Playlist.as

    r242 r374  
    298298                                continue; 
    299299                        } else if(itm == 'image') { 
    300                                 if(config['thumbs'] != false && 
     300                                if(config['thumbs'] != false && view.config['playlist'] != 'none' && 
    301301                                        (view.playlist[idx]['image'] || view.playlist[idx]['playlist.image'])) { 
    302302                                        var img:MovieClip = buttons[idx].c.image; 
  • trunk/as3/com/jeroenwijering/plugins/Rightclick.as

    r211 r374  
    5555                view = vie; 
    5656                view.skin.contextMenu = context; 
    57                 // Add the 'fullscreen' menuitem. 
    5857                try { 
    5958                        fullscreen = new ContextMenuItem('Toggle Fullscreen...'); 
    6059                        addItem(fullscreen,fullscreenHandler); 
    6160                } catch (err:Error) {} 
    62                 // Add the 'stretching' menuitem. 
    6361                stretching = new ContextMenuItem('Stretching is '+view.config['stretching']+'...'); 
    6462                addItem(stretching,stretchHandler); 
    65                 // Add the 'about' menuitem. 
    6663                if(view.config['abouttext'] == 'JW Player' || view.config['abouttext'] == undefined) { 
    6764                        about = new ContextMenuItem('About JW Player '+view.config['version']+'...'); 
     
    7067                } 
    7168                addItem(about,aboutHandler); 
    72                 // Add the 'debug' menuitem. 
    7369                if(Capabilities.isDebugger == true || view.config['debug'] != 'none') { 
    7470                        debug = new ContextMenuItem('Logging to '+Logger.output+'...'); 
  • trunk/as3/com/jeroenwijering/plugins/Watermark.as

    r354 r374  
    44import com.jeroenwijering.events.*; 
    55import com.jeroenwijering.utils.*; 
    6  
    7 import fl.transitions.*; 
    8 import fl.transitions.easing.*; 
    96 
    107import flash.display.*; 
     
    2320        public var clip:MovieClip; 
    2421        /** Configuration flashvars pushed by the player. **/ 
    25         public var config:Object = {}; 
     22        public var config:Object = { 
     23                position:'over' 
     24        }; 
    2625        /** Configuration flashvars, not overwritten by the player. **/ 
    2726        private var _config:Object = { 
     
    6160        /** Fade out watermark. **/ 
    6261        private function hide():void { 
    63                 _config['state'] = false; 
    64                 clip.mouseEnabled = false; 
    65                 TransitionManager.start(clip,{ 
    66                         type:Fade, 
    67                         direction:Transition.OUT, 
    68                         duration:0.3, 
    69                         easing:Regular.easeIn 
    70                 }); 
     62                Animations.fade(clip,0,0.1); 
    7163        }; 
    7264 
     
    8072                        for (var i:String in config) { _config[i] = config[i]; } 
    8173                } 
    82                 clip.visible = false; 
    83                 clip.alpha = _config['out']; 
    8474                clip.buttonMode = true; 
    8575                clip.addEventListener(MouseEvent.CLICK,clickHandler); 
     
    9484                        loader.load(new URLRequest(_config['file'])); 
    9585                } 
     86                clip.alpha = 0; 
     87                clip.visible = false; 
    9688        }; 
    9789 
     
    10698        /** Handle mouse out state **/ 
    10799        private function outHandler(evt:MouseEvent):void { 
    108                 clip.alpha = _config['out']; 
     100                Animations.fade(clip,0,0.2); 
    109101        }; 
    110102 
     
    112104        /** Handle mouse over state **/ 
    113105        private function overHandler(evt:MouseEvent):void { 
    114                 clip.alpha = _config['over']; 
     106                clearTimeout(timeout); 
     107                Animations.fade(clip,_config['over'],0.1); 
    115108        }; 
    116109 
     
    135128        /** Fade in watermark. **/ 
    136129        private function show():void { 
    137                 if(!_config['state']) { 
    138                         _config['state'] = true; 
    139                         TransitionManager.start(clip,{ 
    140                                 type:Fade, 
    141                                 direction:Transition.IN, 
    142                                 duration:0.3, 
    143                                 easing:Regular.easeIn 
    144                         }); 
    145                 } 
     130                Animations.fade(clip,_config['out'],0.1); 
    146131                timeout = setTimeout(hide,_config['timeout']*1000); 
    147                 clip.mouseEnabled = true; 
    148132        }; 
    149133 
  • trunk/as3/com/jeroenwijering/utils/NetClient.as

    r213 r374  
    3131                        out[i] = dat[i]; 
    3232                } 
    33                 callback.onData(out); 
     33                callback.onClientData(out); 
    3434        }; 
    3535 
  • trunk/as3/com/jeroenwijering/utils/Stretcher.as

    r210 r374  
    2828        * @param hei    The target height. 
    2929        * @param typ    The stretching type. 
    30  *      **/ 
     30        **/ 
    3131        public static function stretch(clp:DisplayObject,wid:Number,hei:Number,typ:String='uniform'):void { 
    3232                var xsc:Number = wid/clp.width; 
  • trunk/as3/yt.as

    r161 r374  
    7373};  
    7474function onPlayerError(erc:Number) { 
    75         _as2_to_as3.send('AS2_'+unique,"onError",stt); 
     75        _as2_to_as3.send('AS2_'+unique,"onError",erc); 
    7676        clearInterval(timeInterval); 
    7777}; 
Note: See TracChangeset for help on using the changeset viewer.