| 1 | /** |
|---|
| 2 | * Parses SRT lists and W3C Timed Text captions. |
|---|
| 3 | * |
|---|
| 4 | * @author Jeroen Wijering |
|---|
| 5 | * @version 1.3 |
|---|
| 6 | **/ |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | import com.jeroenwijering.utils.StringMagic; |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | class com.jeroenwijering.players.CaptionsParser { |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | /** URL of the xml file to parse. **/ |
|---|
| 16 | private var parseURL:String; |
|---|
| 17 | /** The array the XML is parsed into **/ |
|---|
| 18 | public var parseArray:Array; |
|---|
| 19 | /** LoadVars Object the SRT file is loaded into. **/ |
|---|
| 20 | private var parseLV:LoadVars; |
|---|
| 21 | /** Flash XML object the TT file is loaded into. **/ |
|---|
| 22 | private var parseXML:XML; |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | /** Constructor. **/ |
|---|
| 26 | function CaptionsParser() {}; |
|---|
| 27 | |
|---|
| 28 | |
|---|
| 29 | /** Parse an XML list. **/ |
|---|
| 30 | public function parse(url:String):Void { |
|---|
| 31 | parseURL = url; |
|---|
| 32 | parseArray = new Array(); |
|---|
| 33 | parseURL.indexOf(".srt") == -1 ? parseTT(): parseSRT(); |
|---|
| 34 | }; |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | /** Convert SRT file to subtitle array **/ |
|---|
| 38 | private function parseSRT() { |
|---|
| 39 | var ref = this; |
|---|
| 40 | parseLV = new LoadVars(); |
|---|
| 41 | parseLV.onLoad = function(scs:Boolean) { |
|---|
| 42 | if(scs) { |
|---|
| 43 | var str = ""; |
|---|
| 44 | var j = -2; |
|---|
| 45 | while(j < unescape(this).length) { |
|---|
| 46 | var oj = j; |
|---|
| 47 | j = unescape(this).indexOf('=&',j+2); |
|---|
| 48 | j == -1 ? j = unescape(this).length: null; |
|---|
| 49 | str = "&"+unescape(this).substring(oj+2,j) + str; |
|---|
| 50 | } |
|---|
| 51 | var arr = str.split("\r\n\r\n"); |
|---|
| 52 | for(var i=0; i<arr.length; i++) { |
|---|
| 53 | var obj = new Object(); |
|---|
| 54 | var fdd = arr[i].indexOf(":"); |
|---|
| 55 | obj["bgn"] = Number(arr[i].substr(fdd-2,2))*3600 + |
|---|
| 56 | Number(arr[i].substr(fdd+1,2))*60 + |
|---|
| 57 | Number(arr[i].substr(fdd+4,2) + "." + |
|---|
| 58 | arr[i].substr(fdd+7,2)); |
|---|
| 59 | var sdd = arr[i].indexOf(":",fdd+6); |
|---|
| 60 | obj["dur"] = Number(arr[i].substr(sdd-2,2))*3600 + |
|---|
| 61 | Number(arr[i].substr(sdd+1,2))*60 + |
|---|
| 62 | Number(arr[i].substr(sdd+4,2) + "." + |
|---|
| 63 | arr[i].substr(sdd+7,2)) - obj["bgn"]; |
|---|
| 64 | var tst = arr[i].indexOf("\r\n",sdd); |
|---|
| 65 | if(arr[i].indexOf("\r\n",tst+5) > -1) { |
|---|
| 66 | var brp = arr[i].indexOf("\r\n",tst+5); |
|---|
| 67 | arr[i] = arr[i].substr(0,brp)+"<br />" + |
|---|
| 68 | arr[i].substr(brp+2); |
|---|
| 69 | } |
|---|
| 70 | obj["txt"] = arr[i].substr(tst+2); |
|---|
| 71 | if(!isNaN(obj['bgn'])) { |
|---|
| 72 | ref.parseArray.push(obj); |
|---|
| 73 | } |
|---|
| 74 | delete obj; |
|---|
| 75 | } |
|---|
| 76 | } else { |
|---|
| 77 | ref.parseArray.push( {txt:"File not found: " + |
|---|
| 78 | ref.parseURL,bgn:1,dur:5}); |
|---|
| 79 | } |
|---|
| 80 | if(ref.parseArray.length == 0) { |
|---|
| 81 | ref.parseArray.push({txt:"Empty file: " + |
|---|
| 82 | ref.parseURL,bgn:1,dur:5}); |
|---|
| 83 | } |
|---|
| 84 | delete ref.parseLV; |
|---|
| 85 | ref.onParseComplete(); |
|---|
| 86 | }; |
|---|
| 87 | if(_root._url.indexOf("file://") > -1) { |
|---|
| 88 | parseLV.load(parseURL); |
|---|
| 89 | } else if(parseURL.indexOf('?') > -1) { |
|---|
| 90 | parseLV.load(parseURL+'&'+random(999)); |
|---|
| 91 | } else { |
|---|
| 92 | parseLV.load(parseURL+'?'+random(999)); |
|---|
| 93 | } |
|---|
| 94 | }; |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | /** Covert TimedText file to subtitle array. **/ |
|---|
| 98 | private function parseTT():Void { |
|---|
| 99 | var ref = this; |
|---|
| 100 | parseXML = new XML(); |
|---|
| 101 | parseXML.ignoreWhite = true; |
|---|
| 102 | parseXML.onLoad = function(scs:Boolean) { |
|---|
| 103 | if(scs) { |
|---|
| 104 | if(this.firstChild.nodeName.toLowerCase() == "tt") { |
|---|
| 105 | var bdy = this.firstChild.childNodes[1]; |
|---|
| 106 | if(bdy.firstChild.firstChild.attributes.begin==undefined){ |
|---|
| 107 | for(var i=0; i<bdy.childNodes.length; i++) { |
|---|
| 108 | var obj = new Object(); |
|---|
| 109 | var bgn = bdy.childNodes[i].attributes.begin; |
|---|
| 110 | obj["bgn"] = StringMagic.toSeconds(bgn); |
|---|
| 111 | var dur = bdy.childNodes[i].attributes.dur; |
|---|
| 112 | obj["dur"] = StringMagic.toSeconds(dur); |
|---|
| 113 | obj["txt"] = String(bdy.childNodes[i].firstChild.childNodes.join('')); |
|---|
| 114 | ref.parseArray.push(obj); |
|---|
| 115 | } |
|---|
| 116 | } else { |
|---|
| 117 | var div = bdy.firstChild; |
|---|
| 118 | for(var i=0; i<div.childNodes.length; i++) { |
|---|
| 119 | var obj = new Object(); |
|---|
| 120 | var bgn = div.childNodes[i].attributes.begin; |
|---|
| 121 | obj["bgn"] = StringMagic.toSeconds(bgn); |
|---|
| 122 | var end = div.childNodes[i].attributes.end; |
|---|
| 123 | if (end == undefined) { |
|---|
| 124 | var dur = div.childNodes[i].attributes.dur; |
|---|
| 125 | obj["dur"] = StringMagic.toSeconds(dur); |
|---|
| 126 | } else { |
|---|
| 127 | obj["dur"] = StringMagic.toSeconds(end)-obj['bgn']; |
|---|
| 128 | } |
|---|
| 129 | obj["txt"] = div.childNodes[i].childNodes.join(''); |
|---|
| 130 | ref.parseArray.push(obj); |
|---|
| 131 | } |
|---|
| 132 | } |
|---|
| 133 | } |
|---|
| 134 | } else { |
|---|
| 135 | ref.parseArray.push( {txt:"File not found: "+ref.parseURL}); |
|---|
| 136 | } |
|---|
| 137 | if(ref.parseArray.length == 0) { |
|---|
| 138 | ref.parseArray.push({txt:"Incompatible file: "+ref.parseURL}); |
|---|
| 139 | } |
|---|
| 140 | delete ref.parseXML; |
|---|
| 141 | ref.onParseComplete(); |
|---|
| 142 | }; |
|---|
| 143 | if(_root._url.indexOf("file://") > -1) { |
|---|
| 144 | parseXML.load(parseURL); |
|---|
| 145 | } else if(parseURL.indexOf('?') > -1) { |
|---|
| 146 | parseXML.load(parseURL+'&'+random(999)); |
|---|
| 147 | } else { |
|---|
| 148 | parseXML.load(parseURL+'?'+random(999)); |
|---|
| 149 | } |
|---|
| 150 | }; |
|---|
| 151 | |
|---|
| 152 | |
|---|
| 153 | /** Invoked when parsing is completed. **/ |
|---|
| 154 | public function onParseComplete() { }; |
|---|
| 155 | |
|---|
| 156 | |
|---|
| 157 | } |
|---|