source: trunk/as3/com/jeroenwijering/models/RTMPModel.as @ 6

Revision 6, 7.1 KB checked in by jeroen, 5 years ago (diff)

added stacking and first skin (inverted)

  • Property svn:executable set to *
Line 
1/**
2* Wrapper for playback of progressively downloaded video.
3**/
4package com.jeroenwijering.models {
5
6
7import com.jeroenwijering.events.*;
8import com.jeroenwijering.models.ModelInterface;
9import com.jeroenwijering.player.Model;
10import flash.display.DisplayObject;
11import flash.events.*;
12import flash.media.*;
13import flash.net.*;
14import flash.utils.*;
15
16
17public class RTMPModel implements ModelInterface {
18
19
20        /** reference to the model. **/
21        private var model:Model;
22        /** Video object to be instantiated. **/
23        private var video:Video;
24        /** NetConnection object for setup of the video stream. **/
25        private var connection:NetConnection;
26        /** NetStream instance that handles the stream IO. **/
27        private var stream:NetStream;
28        /** Sound control object. **/
29        private var transform:SoundTransform;
30        /** Interval ID for the time. **/
31        private var timeinterval:Number;
32        /** Timeout ID for cleaning up idle streams. **/
33        private var timeout:Number;
34        /** Metadata received switch. **/
35        private var metadata:Boolean;
36
37        /** Constructor; sets up the connection and display. **/
38        public function RTMPModel(mod:Model) {
39                model = mod;
40                connection = new NetConnection();
41                connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
42                connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler);
43                connection.objectEncoding = ObjectEncoding.AMF0;
44                video = new Video(320,240);
45                transform = new SoundTransform();
46                model.config['mute'] == true ? volume(0): volume(model.config['volume']);
47                quality(model.config['quality']);
48        };
49
50
51        /** Catch security errors. **/
52        private function errorHandler(evt:ErrorEvent) {
53                model.sendEvent(ModelEvent.ERROR,{message:evt.text});
54        };
55
56
57        /** xtract the current ID from an RTMP URL **/
58        private function getStream(url:String):String {
59                var i = 0;
60                var idx = 0;
61                do {
62                        idx = url.indexOf('/',idx+1);
63                        i++;
64                } while (i < 4);
65                return url.substr(0,idx);
66        };
67
68
69        /** xtract the current Stream from an RTMP URL **/
70        private function getID(url:String):String {
71                var i = 0;
72                var idx = 0;
73                do {
74                        idx = url.indexOf('/',idx)+1;
75                        i++;
76                } while (i < 4);
77                var str = url.substr(idx);
78                if(str.substr(-4) == '.mp3') {
79                        str = 'mp3:'+str.substr(0,str.length-4);
80                } else if (str.substr(-4) == '.flv'){
81                        str = str.substr(0,str.length-4);
82                }
83                return str;
84        };
85
86
87        /** Load content. **/
88        public function load() {
89                connection.connect(getStream(model.playlist[model.config['item']]['file']));
90                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING});
91        };
92
93
94        /** Forward cuepoint data **/
95        public function onCuePoint(info:Object) {
96                var dat = new Object();
97                for(var i in info) {
98                        dat[i] = info[i];
99                }
100                model.sendEvent(ModelEvent.META,dat);
101        };
102
103        /** Get id3 information from netstream class. **/
104        public function onID3(info:Object) {
105                var dat = new Object();
106                for(var i in info) {
107                        dat[i] = info[i];
108                }
109                model.sendEvent(ModelEvent.META,dat);
110        };
111
112
113        /** Get textdata from netstream. **/
114        public function onImageData(info:Object) {
115                var dat = new Object();
116                for(var i in info) {
117                        dat[i] = info[i];
118                }
119                model.sendEvent(ModelEvent.META,dat);
120        };
121
122
123        /** Get metadata information from netstream class. **/
124        public function onMetaData(info:Object) {
125                if(!metadata) {
126                        metadata = true;
127                        video.width = info.width;
128                        video.height = info.height;
129                        model.mediaHandler(video);
130                        var dat = new Object();
131                        for(var i in info) {
132                                dat[i] = info[i];
133                        }
134                        model.sendEvent(ModelEvent.META,dat);
135                        if(model.playlist[model.config['item']]['start'] > 0) {
136                                seek(model.playlist[model.config['item']]['start']);
137                        }
138                }
139        };
140
141
142        /** Receive NetStream status updates. **/
143        public function onPlayStatus(info:Object) {
144                if(info.code == "NetStream.Play.Complete") {
145                        clearInterval(timeinterval);
146                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED});
147                }
148                var dat = new Object();
149                for(var i in info) {
150                        dat[i] = info[i];
151                }
152                model.sendEvent(ModelEvent.META,dat);
153        };
154
155
156        /** Get textdata from netstream. **/
157        public function onTextData(info:Object) {
158                var dat = new Object();
159                for(var i in info) {
160                        dat[i] = info[i];
161                }
162                model.sendEvent(ModelEvent.META,dat);
163        };
164
165
166        /** Pause playback. **/
167        public function pause() {
168                clearInterval(timeinterval);
169                stream.pause();
170                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED});
171                timeout = setTimeout(stop,10000);
172        };
173
174
175        /** Resume playing. **/
176        public function play() {
177                clearTimeout(timeout);
178                stream.resume();
179                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});
180                timeinterval = setInterval(timeHandler,100);
181        };
182
183
184        /** Change the smoothing mode. **/
185        public function quality(qua:Boolean) {
186                if(qua == true) {
187                        video.smoothing = true;
188                        video.deblocking = 4;
189                } else {
190                        video.smoothing = false;
191                        video.deblocking = 1;
192                }
193        };
194
195
196        /** Change the smoothing mode. **/
197        public function seek(pos:Number) {
198                clearInterval(timeinterval);
199                if(model.config['state'] == ModelStates.PAUSED) {
200                        stream.resume();
201                }
202                stream.seek(pos);
203        };
204
205
206        /** Set streaming object **/
207        public function setStream() {
208                stream = new NetStream(connection);
209                stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
210                stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
211                stream.bufferTime = model.config['bufferlength'];
212                stream.client = this;
213                video.attachNetStream(stream);
214                stream.soundTransform = transform;
215                stream.play(getID(model.playlist[model.config['item']]['file']));
216                timeinterval = setInterval(timeHandler,100);
217        };
218
219
220        /** Receive NetStream status updates. **/
221        private function statusHandler(evt:NetStatusEvent) {
222                if(evt.info.code == "NetConnection.Connect.Success") {
223                        setStream();
224                } else if(evt.info.code == "NetStream.Seek.Notify") {
225                        clearInterval(timeinterval);
226                        timeinterval = setInterval(timeHandler,100);
227                } else if(evt.info.code == "NetStream.Play.StreamNotFound" ||
228                        evt.info.code == "NetConnection.Connect.Rejected" ||
229                        evt.info.code == "NetConnection.Connect.Failed") {
230                        stop();
231                        model.sendEvent(ModelEvent.ERROR,{message:"RTMP stream not found: " +
232                                model.playlist[model.config['item']]['file']});
233                }
234                model.sendEvent(ModelEvent.META,{info:evt.info.code});
235        };
236
237
238        /** Destroy the stream. **/
239        public function stop() {
240                clearInterval(timeinterval);
241                connection.close();
242                video.attachNetStream(null);
243                video.clear();
244                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE});
245        };
246
247
248        /** Interval for the position progress **/
249        private function timeHandler() {
250                var bfr = Math.round(stream.bufferLength/stream.bufferTime*100);
251                var pos = Math.round(stream.time*10)/10;
252                var dur = model.playlist[model.config['item']]['duration'];
253                if(bfr < 100 && pos < dur-stream.bufferTime-1) {
254                        model.sendEvent(ModelEvent.BUFFER,{percentage:bfr});
255                        if(model.config['state'] != ModelStates.BUFFERING) {
256                                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING});
257                        }
258                } else if (model.config['state'] == ModelStates.BUFFERING) {
259                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});
260                }
261                if(dur > 0) {
262                        model.sendEvent(ModelEvent.TIME,{position:pos,duration:dur});
263                }
264        };
265
266
267        /** Set the volume level. **/
268        public function volume(vol:Number) {
269                transform.volume = vol/100;
270                if(stream) {
271                        stream.soundTransform = transform;
272                }
273        };
274
275
276};
277
278
279}
Note: See TracBrowser for help on using the repository browser.