source: plugins/captions/v4/com/jeroenwijering/plugins/Captions.as @ 880

Revision 880, 6.5 KB checked in by jeroen, 3 years ago (diff)

Fixed #767 captions issues and checked in initial version of v5 captions

Line 
1/**
2* Plugin for playing closed captions and a closed audiodescription with a video.
3**/
4package com.jeroenwijering.plugins {
5
6
7import com.jeroenwijering.events.*;
8import com.jeroenwijering.parsers.*;
9import com.jeroenwijering.utils.Logger;
10
11import flash.display.*;
12import flash.events.*;
13import flash.filters.DropShadowFilter;
14import flash.net.*;
15import flash.text.*;
16
17
18public class Captions extends MovieClip implements PluginInterface {
19
20
21        [Embed(source="../../../controlbar.png")]
22        private const ControlbarIcon:Class;
23        [Embed(source="../../../dock.png")]
24        private const DockIcon:Class;
25
26
27        /** List with configuration settings. **/
28        public var config:Object = {
29                back:false,
30                file:undefined,
31                fontsize:14,
32                state:true
33        };
34        /** XML connect and parse object. **/
35        private var loader:URLLoader;
36        /** Reference to the MVC view. **/
37        private var view:AbstractView;
38        /** Icon for the controlbar. **/
39        private var icon:Bitmap;
40        /** Reference to the textfield. **/
41        public var field:TextField;
42        /** Reference to the background graphic. **/
43        private var back:MovieClip;
44        /** The array the captions are loaded into. **/
45        private var captions:Array;
46        /** Textformat entry for the captions. **/
47        private var format:TextFormat;
48        /** Currently active caption. **/
49        private var current:Number;
50        /** Reference to the dock button. **/
51        private var button:MovieClip;
52
53
54        public function Captions() {
55                loader = new URLLoader();
56                loader.addEventListener(Event.COMPLETE,loaderHandler);
57        };
58
59
60        /** Clicking the  hide button. **/
61        private function clickHandler(evt:MouseEvent):void {
62                hide(!config['state']);
63        };
64
65
66        private function drawClip():void {
67                back = new MovieClip();
68                back.graphics.beginFill(0x000000,0.75);
69                back.graphics.drawRect(0,0,400,20);
70                addChild(back);
71                back.mouseEnabled = false;
72                format = new TextFormat();
73                format.color = 0xFFFFFF;
74                format.size = config['fontsize'];
75                format.align = "center";
76                format.font = "_sans";
77                format.leading = 4;
78                field = new TextField();
79                field.width = 400;
80                field.height = 1;
81                field.y = 5;
82                field.autoSize = "center";
83                field.selectable = false;
84                field.multiline = true;
85                field.wordWrap = true;
86                field.defaultTextFormat = format;
87                field.text = '';
88                addChild(field);
89                field.mouseEnabled = false;
90                if(config['back'] == false) {
91                        back.alpha = 0;
92                        field.filters = new Array(new DropShadowFilter(0,45,0,1,2,2,10,3));
93                }
94        };
95
96
97        /** Show/hide the captions **/
98        public function hide(stt:Boolean):void {
99                config['state'] = stt;
100                visible = config['state'];
101                if(config['state']) {
102                        if(button) {
103                                button.field.text = 'is on';
104                        } else {
105                                icon.alpha = 1;
106                        }
107                } else {
108                        if(button) {
109                                button.field.text = 'is off';
110                        } else {
111                                icon.alpha = 0.3;
112                        }
113                }
114                var cke:SharedObject = SharedObject.getLocal('com.jeroenwijering','/');
115                cke.data['captions.state'] = stt;
116                cke.flush();
117        };
118
119
120        /** Initing the plugin. **/
121        public function initializePlugin(vie:AbstractView):void {
122                view = vie;
123                view.addControllerListener(ControllerEvent.ITEM,itemHandler);
124                view.addControllerListener(ControllerEvent.RESIZE,resizeHandler);
125                view.addModelListener(ModelEvent.TIME,timeHandler);
126                view.addModelListener(ModelEvent.STATE,stateHandler);
127                view.addModelListener(ModelEvent.META,metaHandler);
128                drawClip();
129                if(view.config['dock']) {
130                        button = view.getPlugin('dock').addButton(new DockIcon(),'is on',clickHandler);
131                } else if (view.getPlugin('controlbar')) {
132                        icon = new ControlbarIcon();
133                        view.getPlugin('controlbar').addButton(icon,'captions',clickHandler);
134                }
135                hide(config['state']);
136        };
137
138
139        /** Check for captions with a new item. **/
140        private function itemHandler(evt:ControllerEvent=null):void {
141                current = 0;
142                captions = new Array();
143                config['file'] = undefined;
144                field.htmlText = '';
145                var file:String;
146                if (view.playlist[view.config['item']]['captions.file']){
147                        file = view.playlist[view.config['item']]['captions.file'];
148                } else if (view.playlist[view.config['item']]['captions']){
149                        file = view.playlist[view.config['item']]['captions'];
150                } else if(view.config['captions.file']) {
151                        file = view.config['captions.file'];
152                } else if(view.config['captions']) {
153                        file = view.config['captions'];
154                }
155                if(file) {
156                        config['file'] = file;
157                        try {
158                                loader.load(new URLRequest(config['file']));
159                        } catch (err:Error) {
160                                Logger.log(err.message,'captions');
161                        }
162                }
163        };
164
165
166        /** Captions are loaded; now display them. **/
167        private function loaderHandler(evt:Event):void {
168                var ext:String = config['file'].substr(-3);
169                if(ext == 'srt' || ext == 'txt') {
170                        captions = SRTParser.parseCaptions(String(evt.target.data));
171                } else {
172                        captions = TTParser.parseCaptions(XML(evt.target.data));
173                }
174                if(captions.length == 0) {
175                        Logger.log('Not a valid TimedText or SRT file.','captions');
176                }
177        };
178
179
180        /** Check for captions in metadata. **/
181        private function metaHandler(evt:ModelEvent):void {
182                var txt:String;
183                var fnd:Boolean;
184                if(evt.data.type == 'caption') {
185                        txt = evt.data.captions;
186                        fnd = true;
187                } else if (evt.data.type == 'textdata') {
188                        txt = evt.data.text;
189                        fnd = true;
190                }
191                if(fnd == true) {
192                        field.htmlText = txt+' ';
193                        resizeHandler();
194                        Logger.log(txt,'caption');
195                }
196        };
197
198
199        /** Resize the captions if the display changes. **/
200        private function resizeHandler(evt:ControllerEvent=undefined):void {
201                if(field.length > 3) {
202                        back.height = field.height + 10;
203                } else {
204                        back.height = 0;
205                }
206                width = view.config['width'];
207                scaleY = scaleX;
208                y = view.config['height']-height;
209                if(view.config['controlbar'] == 'over' || view.config['fullscreen']) {
210                        y -= 50;
211                }
212        };
213
214
215        /** Set a caption on screen. **/
216        private function setCaption(pos:Number):void {
217                for(var i:Number=0; i<captions.length; i++) {
218                        if(captions[i]['begin'] < pos && (i == captions.length - 1 || captions[i+1]['begin'] > pos)) {
219                                current = i;
220                                field.htmlText = captions[i]['text'];
221                                resizeHandler();
222                                Logger.log(captions[i]['text'],'caption');
223                                return;
224                        }
225                }
226        };
227
228
229        /** Check timing of the player to sync captions. **/
230        private function stateHandler(evt:ModelEvent):void {
231                if((view.config['state'] == ModelStates.PLAYING ||
232                        view.config['state'] == ModelStates.PAUSED) && config['state']) {
233                        visible = true;
234                } else {
235                        visible = false;
236                }
237        };
238
239
240        /** Check timing of the player to sync captions. **/
241        private function timeHandler(evt:ModelEvent):void {
242                var pos:Number = evt.data.position;
243                if(captions && captions.length > 0 && (
244                        captions[current]['begin'] > pos ||
245                        (captions[current+1] && captions[current+1]['begin'] < pos))) {
246                        setCaption(pos);
247                }
248        };
249
250
251};
252
253
254}
Note: See TracBrowser for help on using the repository browser.