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

Revision 826, 6.7 KB checked in by pablo, 3 years ago (diff)
  • Clean up for locking scenarios
  • MediaEvent.JWPLAYER_MEDIA_VOLUME event not sent on every item load (only sent in response to a setVolume() call)
  • DisplayComponent dispatches PLAY and PAUSE events, in addition to DISPLAY_CLICK
  • PlaylistComponent dispatches ITEM events
  • Debug options visible in right-click menu when "debug" flashvar is set, even when using the non-debug Flash Player
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                /** xtract the current ID from a youtube URL **/
68                private function getID(url:String):String {
69                        var arr:Array = url.split('?');
70                        var str:String = '';
71                        for (var i:String in arr) {
72                                if (arr[i].substr(0, 2) == 'v=') {
73                                        str = arr[i].substr(2);
74                                }
75                        }
76                        if (str == '') {
77                                str = url.substr(url.indexOf('/v/') + 3);
78                        }
79                        if (str.indexOf('&') > -1) {
80                                str = str.substr(0, str.indexOf('&'));
81                        }
82                        return str;
83                }
84
85
86                /** Get the location of yt.swf. **/
87                private function getLocation():String {
88                        var loc:String;
89                        var url:String = RootReference.stage.loaderInfo.url;
90                        if (url.indexOf('http://') == 0) {
91                                _unique = Math.random().toString().substr(2);
92                                loc = url.substr(0, url.indexOf('.swf'));
93                                loc = loc.substr(0, loc.lastIndexOf('/') + 1) + 'yt.swf?unique=' + _unique;
94                        } else {
95                                _unique = '1';
96                                loc = 'yt.swf';
97                        }
98                        return loc;
99                }
100
101
102                /** Load the YouTube movie. **/
103                override public function load(itm:PlaylistItem):void {
104                        _item = itm;
105                        _position = _offset = 0;
106                        _loading = true;
107                        setState(PlayerState.BUFFERING);
108                        if (_connected) {
109                                completeLoad(itm);
110                        } else {
111                                _loader.load(new URLRequest(getLocation()));
112                                _inbound.connect('AS2_' + _unique);
113                        }
114                }
115
116
117                /** SWF loaded; add it to the tree **/
118                public function onSwfLoadComplete():void {
119                        _connected = true;
120                        if (_loading) {
121                                completeLoad(_item);
122                        }
123                }
124
125
126                /** Everything loaded - play the video **/
127                private function completeLoad(itm:PlaylistItem):void {
128                        if (_outgoing) {
129                                var gid:String = getID(_item.file);
130                                _outgoing.send('AS3_' + _unique, "cueVideoById", gid, _item.start);
131                                resize(config.width, config.width / 4 * 3);
132                                media = _loader;
133                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
134                                sendBufferEvent(0);
135                                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL);
136                                _outgoing.send('AS3_' + _unique, "setVolume", (config.mute ? 0 : config.volume / 100));
137                        }
138                }
139
140
141                /** Pause the YouTube movie. **/
142                override public function pause():void {
143                        if (state == PlayerState.PLAYING || state == PlayerState.BUFFERING) {
144                                _outgoing.send('AS3_' + _unique, "pauseVideo");
145                        }
146                        super.pause();
147                }
148
149
150                /** Play or pause the video. **/
151                override public function play():void {
152                        _outgoing.send('AS3_' + _unique, "playVideo");
153//                      super.play();
154                }
155
156
157                /** error was thrown without this handler **/
158                public function onLocalConnectionStatusChange(evt:StatusEvent):void {
159                        // sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META,{status:evt.code});
160                }
161
162
163                /** Catch youtube errors. **/
164                public function onError(erc:Number):void {
165                        var msg:String = 'Video not found or deleted: ' + getID(item['file']);
166                        if (erc == 101 || erc == 150) {
167                                msg = 'Embedding this video is disabled by its owner.';
168                        }
169                        error(msg);
170                }
171
172
173                /** Catch youtube state changes. **/
174                public function onStateChange(stt:Number):void {
175                        switch (Number(stt)) {
176                                case -1:
177                                        // setState(PlayerState.IDLE);
178                                        break;
179                                case 0:
180                                        if (state != PlayerState.BUFFERING && state != PlayerState.IDLE) {
181                                                complete();
182                                                _offset = 0;
183                                        }
184                                        break;
185                                case 1:
186                                        super.play();
187                                        break;
188                                case 2:
189                                        super.pause();
190                                        break;
191                                case 3:
192                                        setState(PlayerState.BUFFERING);
193                                        break;
194                        }
195                }
196
197
198                /** Catch Youtube load changes **/
199                public function onLoadChange(ldd:Number, ttl:Number, off:Number):void {
200                        _bufferPercent = Math.round(ldd / ttl * 100);
201                        _offset = off / ttl * item.duration;
202                        sendBufferEvent(_bufferPercent, _offset);
203                }
204
205
206                /** Catch Youtube _position changes **/
207                public function onTimeChange(pos:Number, dur:Number):void {
208                        _position = pos;
209                        if (item.duration < 0) {
210                                item.duration = dur;
211                        }
212                        if (state != PlayerState.PLAYING){
213                                super.play();
214                        }
215                        sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: pos, duration: item.duration, offset: _offset});
216                        if (pos > item.duration) {
217                                complete();
218                        }
219                }
220
221
222                /** Resize the YT player. **/
223                public override function resize(wid:Number, hei:Number):void {
224                        _outgoing.send('AS3_' + _unique, "setSize", wid, hei);
225                }
226
227
228                /** Seek to _position. **/
229                override public function seek(pos:Number):void {
230                        super.seek(pos);
231                        _outgoing.send('AS3_' + _unique, "seekTo", pos);
232                        play();
233                }
234
235
236                /** Destroy the youtube video. **/
237                override public function stop():void {
238                        if (_connected) {
239                                _outgoing.send('AS3_' + _unique, "stopVideo");
240                        } else {
241                                _loading = false;
242                        }
243                        _position = _offset = 0;
244                        super.stop();
245                }
246
247
248                /** Set the volume level. **/
249                override public function setVolume(pct:Number):void {
250                        _outgoing.send('AS3_' + _unique, "setVolume", pct);
251                        super.setVolume(pct);
252                }
253        }
254}
Note: See TracBrowser for help on using the repository browser.