source: trunk/fl5/src/com/longtailvideo/jwplayer/media/YouTubeMediaProvider.as @ 1003

Revision 1003, 6.9 KB checked in by pablo, 4 years ago (diff)

Support upcoming YouTube URL changes (781)

Line 
1/**
2 * Wrapper for load and playback of Youtube videos through their API.
3 **/
4package com.longtailvideo.jwplayer.media {
5        import com.jeroenwijering.events.*;
6        import com.longtailvideo.jwplayer.events.MediaEvent;
7        import com.longtailvideo.jwplayer.model.PlayerConfig;
8        import com.longtailvideo.jwplayer.model.PlaylistItem;
9        import com.longtailvideo.jwplayer.player.PlayerState;
10        import com.longtailvideo.jwplayer.utils.RootReference;
11       
12        import flash.display.Loader;
13        import flash.events.*;
14        import flash.net.LocalConnection;
15        import flash.net.URLRequest;
16        import flash.system.Security;
17
18
19        public class YouTubeMediaProvider extends MediaProvider {
20                /** Loader for loading the YouTube proxy **/
21                private var _loader:Loader;
22                /** 'Unique' string to use for proxy connection. **/
23                private var _unique:String;
24                /** Connection towards the YT proxy. **/
25                private var _outgoing:LocalConnection;
26                /** connection from the YT proxy. **/
27                private var _inbound:LocalConnection;
28                /** Save that a load call has been sent. **/
29                private var _loading:Boolean;
30                /** Save the connection state. **/
31                private var _connected:Boolean;
32                /** Buffer percent **/
33                private var _bufferPercent:Number;
34                /** Time offset **/
35                private var _offset:Number = 0;
36
37
38                /** Setup YouTube connections and load proxy. **/
39                public function YouTubeMediaProvider() {
40                        super('youtube');
41                }
42
43
44                public override function initializeMediaProvider(cfg:PlayerConfig):void {
45                        super.initializeMediaProvider(cfg);
46                        Security.allowDomain('*');
47                        _outgoing = new LocalConnection();
48                        _outgoing.allowDomain('*');
49                        _outgoing.allowInsecureDomain('*');
50                        _outgoing.addEventListener(StatusEvent.STATUS, onLocalConnectionStatusChange);
51                        _inbound = new LocalConnection();
52                        _inbound.allowDomain('*');
53                        _inbound.allowInsecureDomain('*');
54                        _inbound.addEventListener(StatusEvent.STATUS, onLocalConnectionStatusChange);
55                        _inbound.client = this;
56                        _loader = new Loader();
57                        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
58                }
59
60
61                /** Catch load errors. **/
62                private function errorHandler(evt:ErrorEvent):void {
63                        error(evt.text);
64                }
65
66
67                /** Extract the current ID from a youtube URL.  Supported values include:
68                 * http://www.youtube.com/watch?v=ylLzyHk54Z0
69                 * http://www.youtube.com/watch#!v=ylLzyHk54Z0
70                 * http://www.youtube.com/v/ylLzyHk54Z0
71                 * ylLzyHk54Z0
72                 **/
73                private function getID(url:String):String {
74                        var arr:Array = url.split(/\?|\#\!/);
75                        var str:String = '';
76                        for (var i:String in arr) {
77                                if (arr[i].substr(0, 2) == 'v=') {
78                                        str = arr[i].substr(2);
79                                }
80                        }
81                        if (str == '') {
82                                if (url.indexOf('/v/') >= 0) {
83                                        str = url.substr(url.indexOf('/v/') + 3);
84                                } else {
85                                        str = url;
86                                }
87                        }
88                        if (str.indexOf('&') > -1) {
89                                str = str.substr(0, str.indexOf('&'));
90                        }
91                        return str;
92                }
93
94
95                /** Get the location of yt.swf. **/
96                private function getLocation():String {
97                        var loc:String;
98                        var url:String = RootReference.stage.loaderInfo.url;
99                        if (url.indexOf('http') == 0) {
100                                _unique = Math.random().toString().substr(2);
101                                loc = url.substr(0, url.indexOf('.swf'));
102                                loc = loc.substr(0, loc.lastIndexOf('/') + 1) + 'yt.swf?unique=' + _unique;
103                        } else {
104                                _unique = '1';
105                                loc = 'yt.swf';
106                        }
107                        return loc;
108                }
109
110
111                /** Load the YouTube movie. **/
112                override public function load(itm:PlaylistItem):void {
113                        _item = itm;
114                        _position = _offset = 0;
115                        _loading = true;
116                        setState(PlayerState.BUFFERING);
117                        if (_connected) {
118                                completeLoad(itm);
119                        } else {
120                                _loader.load(new URLRequest(getLocation()));
121                                _inbound.connect('AS2_' + _unique);
122                        }
123                }
124
125
126                /** SWF loaded; add it to the tree **/
127                public function onSwfLoadComplete():void {
128                        _connected = true;
129                        if (_loading) {
130                                completeLoad(_item);
131                        }
132                }
133
134
135                /** Everything loaded - play the video **/
136                private function completeLoad(itm:PlaylistItem):void {
137                        if (_outgoing) {
138                                var gid:String = getID(_item.file);
139                                _outgoing.send('AS3_' + _unique, "cueVideoById", gid, _item.start);
140                                resize(config.width, config.width / 4 * 3);
141                                media = _loader;
142                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
143                                sendBufferEvent(0);
144                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL);
145                                _outgoing.send('AS3_' + _unique, "setVolume", (config.mute ? 0 : config.volume));
146                        }
147                }
148
149
150                /** Pause the YouTube movie. **/
151                override public function pause():void {
152                        if (state == PlayerState.PLAYING || state == PlayerState.BUFFERING) {
153                                _outgoing.send('AS3_' + _unique, "pauseVideo");
154                        }
155                        super.pause();
156                }
157
158
159                /** Play or pause the video. **/
160                override public function play():void {
161                        _outgoing.send('AS3_' + _unique, "playVideo");
162                        super.play();
163                }
164
165
166                /** error was thrown without this handler **/
167                public function onLocalConnectionStatusChange(evt:StatusEvent):void {
168                        // sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META,{status:evt.code});
169                }
170
171
172                /** Catch youtube errors. **/
173                public function onError(erc:Number):void {
174                        var msg:String = 'Video not found or deleted: ' + getID(item['file']);
175                        if (erc == 101 || erc == 150) {
176                                msg = 'Embedding this video is disabled by its owner.';
177                        }
178                        error(msg);
179                }
180
181
182                /** Catch youtube state changes. **/
183                public function onStateChange(stt:Number):void {
184                        switch (Number(stt)) {
185                                case 0:
186                                        if (state != PlayerState.BUFFERING && state != PlayerState.IDLE) {
187                                                complete();
188                                                _offset = 0;
189                                        }
190                                        break;
191                                case 1:
192                                        super.play();
193                                        break;
194                                case 2:
195                                        super.pause();
196                                        break;
197                                case 3:
198                                        setState(PlayerState.BUFFERING);
199                                        break;
200                        }
201                }
202
203
204                /** Catch Youtube load changes **/
205                public function onLoadChange(ldd:Number, ttl:Number, off:Number):void {
206                        _bufferPercent = Math.round(ldd / ttl * 100);
207                        _offset = off / ttl * item.duration;
208                        sendBufferEvent(_bufferPercent, _offset, {loaded:ldd, total:ttl});
209                }
210
211
212                /** Catch Youtube _position changes **/
213                public function onTimeChange(pos:Number, dur:Number):void {
214                        if (state == PlayerState.PLAYING) {
215                       
216                                _position = pos;
217                                if (item.duration < 0) {
218                                        item.duration = dur;
219                                }
220                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: pos, duration: item.duration, offset: _offset});
221                                if (pos > item.duration) {
222                                        complete();
223                                }
224                        }
225                }
226               
227
228                /** Resize the YT player. **/
229                public override function resize(wid:Number, hei:Number):void {
230                        _outgoing.send('AS3_' + _unique, "setSize", wid, hei);
231                }
232
233
234                /** Seek to _position. **/
235                override public function seek(pos:Number):void {
236                        super.seek(pos);
237                        _outgoing.send('AS3_' + _unique, "seekTo", pos);
238                        play();
239                }
240
241
242                /** Destroy the youtube video. **/
243                override public function stop():void {
244                        if (_connected) {
245                                _outgoing.send('AS3_' + _unique, "stopVideo");
246                        } else {
247                                _loading = false;
248                        }
249                        _position = _offset = 0;
250                        super.stop();
251                }
252
253
254                /** Set the volume level. **/
255                override public function setVolume(pct:Number):void {
256                        _outgoing.send('AS3_' + _unique, "setVolume", pct);
257                        super.setVolume(pct);
258                }
259        }
260}
Note: See TracBrowser for help on using the repository browser.