source: trunk/as3/com/jeroenwijering/models/VideoModel.as @ 224

Revision 224, 5.6 KB checked in by jeroen, 4 years ago (diff)

three fixes: serurity error code for plugins now handled, masks for the display not assigned twice, error message for video-not-found more generic (includes access denied)

  • 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.AbstractModel;
9import com.jeroenwijering.player.Model;
10import com.jeroenwijering.utils.NetClient;
11
12import flash.events.*;
13import flash.media.*;
14import flash.net.*;
15import flash.utils.*;
16
17
18public class VideoModel extends AbstractModel {
19
20
21        /** 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;
35
36
37        /** Constructor; sets up the connection and display. **/
38        public function VideoModel(mod:Model):void {
39                super(mod);
40                connection = new NetConnection();
41                connection.connect(null);
42                stream = new NetStream(connection);
43                stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
44                stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
45                stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler);
46                stream.bufferTime = model.config['bufferlength'];
47                stream.client = new NetClient(this);
48                video = new Video(320,240);
49                video.smoothing = model.config['smoothing'];
50                video.attachNetStream(stream);
51                transform = new SoundTransform();
52        };
53
54
55        /** Catch security errors. **/
56        protected function errorHandler(evt:ErrorEvent):void {
57                stop();
58                model.sendEvent(ModelEvent.ERROR,{message:evt.text});
59        };
60
61
62        /** Load content. **/
63        override public function load(itm:Object):void {
64                item = itm;
65                position = 0;
66                model.mediaHandler(video);
67                stream.checkPolicyFile = true;
68                stream.play(item['file']);
69                interval = setInterval(positionInterval,100);
70                loadinterval = setInterval(loadHandler,200);
71                model.config['mute'] == true ? volume(0): volume(model.config['volume']);
72                model.sendEvent(ModelEvent.BUFFER,{percentage:0});
73                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING});
74        };
75
76
77        /** Interval for the loading progress **/
78        protected function loadHandler():void {
79                var ldd:Number = stream.bytesLoaded;
80                var ttl:Number = stream.bytesTotal;
81                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                var obj:Object = new Object();
94                obj['bandwidth'] = Math.round(stream.bytesLoaded/1024/3*8);
95                if(item['duration']) {
96                        obj['bitrate'] = Math.round(stream.bytesTotal/1024*8/item['duration']);
97                }
98                model.sendEvent('META',obj);
99        };
100
101
102        /** Get metadata information from netstream class. **/
103        public function onData(dat:Object):void {
104                if(dat.width) {
105                        video.width = dat.width;
106                        video.height = dat.height;
107                }
108                model.sendEvent(ModelEvent.META,dat);
109        };
110
111
112        /** Pause playback. **/
113        override public function pause():void {
114                stream.pause();
115                clearInterval(interval);
116                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED});
117        };
118
119
120        /** Resume playing. **/
121        override public function play():void {
122                stream.resume();
123                interval = setInterval(positionInterval,100);
124                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});
125        };
126
127
128        /** Interval for the position progress **/
129        protected function positionInterval():void {
130                position = Math.round(stream.time*10)/10;
131                var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100);
132                if(bfr < 95 && position < Math.abs(item['duration']-stream.bufferTime-1)) {
133                        model.sendEvent(ModelEvent.BUFFER,{percentage:bfr});
134                        if(model.config['state'] != ModelStates.BUFFERING && bfr < 25) {
135                                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING});
136                        }
137                } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) {
138                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});
139                }
140                if(position < item['duration']) {
141                        model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration']});
142                } else if (item['duration'] > 0) {
143                        stream.pause();
144                        clearInterval(interval);
145                        model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED});
146                }
147        };
148
149
150        /** Seek to a new position. **/
151        override public function seek(pos:Number):void {
152                position = pos;
153                clearInterval(interval);
154                stream.seek(position);
155                play();
156        };
157
158
159        /** Receive NetStream status updates. **/
160        protected function statusHandler(evt:NetStatusEvent):void {
161                switch (evt.info.code) {
162                        case "NetStream.Play.Stop":
163                                clearInterval(interval);
164                                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED});
165                                break;
166                        case "NetStream.Play.StreamNotFound":
167                                stop();
168                                model.sendEvent(ModelEvent.ERROR,{message:'Video not found or access denied: '+item['file']});
169                                break;
170                        default:
171                                model.sendEvent(ModelEvent.META,{info:evt.info.code});
172                                break;
173                }
174        };
175
176
177        /** Destroy the video. **/
178        override public function stop():void {
179                if(stream.bytesLoaded < stream.bytesTotal) {
180                        stream.close();
181                } else {
182                        stream.pause();
183                }
184                loadtimer = undefined;
185                clearInterval(loadinterval);
186                clearInterval(interval);
187                position = 0;
188                model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE});
189        };
190
191
192        /** Set the volume level. **/
193        override public function volume(vol:Number):void {
194                transform.volume = vol/100;
195                stream.soundTransform = transform;
196        };
197
198
199};
200
201
202}
Note: See TracBrowser for help on using the repository browser.