| 1 | /** |
|---|
| 2 | * Parses RSS, ATOM and XSPF lists and returns them as a numerical array. |
|---|
| 3 | * |
|---|
| 4 | * @author Jeroen Wijering |
|---|
| 5 | * @version 1.7 |
|---|
| 6 | **/ |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | import com.jeroenwijering.feeds.*; |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | class com.jeroenwijering.feeds.FeedManager { |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | /** The array the XML is parsed into. **/ |
|---|
| 16 | public var feed:Array; |
|---|
| 17 | /** XML file **/ |
|---|
| 18 | private var feedXML:XML; |
|---|
| 19 | /** Flag for captions. **/ |
|---|
| 20 | public var captions:Boolean; |
|---|
| 21 | /** Flag for extra audiotrack. **/ |
|---|
| 22 | public var audio:Boolean; |
|---|
| 23 | /** Flag for all items in mp3 **/ |
|---|
| 24 | public var onlymp3s:Boolean; |
|---|
| 25 | /** Flag for chapter index **/ |
|---|
| 26 | public var ischapters:Boolean; |
|---|
| 27 | /** Flag for enclosures **/ |
|---|
| 28 | private var enclosures:Boolean; |
|---|
| 29 | /** Reference to the parser object **/ |
|---|
| 30 | private var parser:AbstractParser; |
|---|
| 31 | /** An array with objects listening to feed updates **/ |
|---|
| 32 | private var listeners:Array; |
|---|
| 33 | /** A prefix string for all files **/ |
|---|
| 34 | private var prefix:String = ""; |
|---|
| 35 | /** Stream to use **/ |
|---|
| 36 | private var stream:String; |
|---|
| 37 | /** Array with all file elements **/ |
|---|
| 38 | private var elements:Object = { |
|---|
| 39 | file:"", |
|---|
| 40 | fallback:"", |
|---|
| 41 | title:"", |
|---|
| 42 | link:"", |
|---|
| 43 | id:"", |
|---|
| 44 | image:"", |
|---|
| 45 | author:"", |
|---|
| 46 | captions:"", |
|---|
| 47 | audio:"", |
|---|
| 48 | category:"", |
|---|
| 49 | start:"", |
|---|
| 50 | type:"", |
|---|
| 51 | duration:"" |
|---|
| 52 | }; |
|---|
| 53 | /** array with all supported filetypes **/ |
|---|
| 54 | private var filetypes:Array = new Array( |
|---|
| 55 | "flv","mp3","rbs","jpg","gif","png","rtmp", |
|---|
| 56 | "swf","mp4","m4v","m4a","mov","3gp","3g2" |
|---|
| 57 | ); |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | /** Constructor. **/ |
|---|
| 61 | function FeedManager(enc:Boolean,jvs:String,pre:String,str:String) { |
|---|
| 62 | enc == true ? enclosures = true: enclosures = false; |
|---|
| 63 | if(jvs == "true") { enableJavascript(); } |
|---|
| 64 | pre == undefined ? null: prefix = pre; |
|---|
| 65 | str == undefined ? null: stream = "_"+str; |
|---|
| 66 | listeners = new Array(); |
|---|
| 67 | }; |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | /** Enable javascript access to loadFile command. **/ |
|---|
| 71 | private function enableJavascript() { |
|---|
| 72 | if(flash.external.ExternalInterface.available) { |
|---|
| 73 | flash.external.ExternalInterface.addCallback( |
|---|
| 74 | "loadFile",this,loadFile); |
|---|
| 75 | flash.external.ExternalInterface.addCallback( |
|---|
| 76 | "addItem",this,addItem); |
|---|
| 77 | flash.external.ExternalInterface.addCallback( |
|---|
| 78 | "removeItem",this,removeItem); |
|---|
| 79 | flash.external.ExternalInterface.addCallback( |
|---|
| 80 | "itemData",this,itemData); |
|---|
| 81 | flash.external.ExternalInterface.addCallback( |
|---|
| 82 | "getLength",this,getLength); |
|---|
| 83 | } |
|---|
| 84 | }; |
|---|
| 85 | |
|---|
| 86 | |
|---|
| 87 | /** Load an XML playlist or single media file. **/ |
|---|
| 88 | public function loadFile(obj:Object) { |
|---|
| 89 | feed = new Array(); |
|---|
| 90 | var ftp = "xml"; |
|---|
| 91 | for(var i = filetypes.length; --i >= 0;) { |
|---|
| 92 | if(obj['file'].substr(0,4).toLowerCase() == "rtmp") { |
|---|
| 93 | ftp = "rtmp"; |
|---|
| 94 | } else if(obj['file'].indexOf('youtube.com') > -1) { |
|---|
| 95 | ftp = "youtube"; |
|---|
| 96 | } else if(obj['type'] == filetypes[i]) { |
|---|
| 97 | ftp = filetypes[i]; |
|---|
| 98 | } else if (obj['file'].substr(-3).toLowerCase() == filetypes[i]) { |
|---|
| 99 | ftp = filetypes[i]; |
|---|
| 100 | } |
|---|
| 101 | } |
|---|
| 102 | if (ftp == "xml") { |
|---|
| 103 | loadXML(unescape(obj['file'])); |
|---|
| 104 | } else { |
|---|
| 105 | feed[0] = new Object(); |
|---|
| 106 | feed[0]['type'] = ftp; |
|---|
| 107 | for(var itm in elements) { |
|---|
| 108 | if(obj[itm] != undefined) { |
|---|
| 109 | feed[0][itm] = obj[itm]; |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | playersPostProcess(); |
|---|
| 113 | } |
|---|
| 114 | }; |
|---|
| 115 | |
|---|
| 116 | |
|---|
| 117 | /** Parse an XML file, return the array when done. **/ |
|---|
| 118 | private function loadXML(url:String) { |
|---|
| 119 | var ref = this; |
|---|
| 120 | feedXML = new XML(); |
|---|
| 121 | feedXML.ignoreWhite = true; |
|---|
| 122 | feedXML.onLoad = function(scs:Boolean) { |
|---|
| 123 | if(scs) { |
|---|
| 124 | var fmt = this.firstChild.nodeName.toLowerCase(); |
|---|
| 125 | if( fmt == 'rss') { |
|---|
| 126 | ref.parser = new RSSParser(ref.prefix); |
|---|
| 127 | ref.feed = ref.parser.parse(this); |
|---|
| 128 | } else if (fmt == 'feed') { |
|---|
| 129 | ref.parser = new ATOMParser(ref.prefix); |
|---|
| 130 | ref.feed = ref.parser.parse(this); |
|---|
| 131 | } else if (fmt == 'playlist') { |
|---|
| 132 | ref.parser = new XSPFParser(ref.prefix); |
|---|
| 133 | ref.feed = ref.parser.parse(this); |
|---|
| 134 | } else if (fmt == 'asx') { |
|---|
| 135 | ref.parser = new ASXParser(ref.prefix); |
|---|
| 136 | ref.feed = ref.parser.parse(this); |
|---|
| 137 | } else if (fmt == 'videolist') { |
|---|
| 138 | ref.parser = new AgriyaParser(ref.prefix); |
|---|
| 139 | ref.feed = ref.parser.parse(this); |
|---|
| 140 | } |
|---|
| 141 | if(_root.audio != undefined) { |
|---|
| 142 | ref.feed[0]["audio"] = unescape(_root.audio); |
|---|
| 143 | } |
|---|
| 144 | ref.playersPostProcess(url); |
|---|
| 145 | } |
|---|
| 146 | }; |
|---|
| 147 | if(_root._url.indexOf("file://") > -1) { feedXML.load(url); } |
|---|
| 148 | else if(url.indexOf('?') > -1) { feedXML.load(url+'&'+random(999)); } |
|---|
| 149 | else { feedXML.load(url+'?'+random(999)); } |
|---|
| 150 | }; |
|---|
| 151 | |
|---|
| 152 | |
|---|
| 153 | /** set a number of flags specifically used by the players **/ |
|---|
| 154 | private function playersPostProcess(url:String) { |
|---|
| 155 | onlymp3s = true; |
|---|
| 156 | feed.length > 1 ? ischapters = true: ischapters = false; |
|---|
| 157 | captions = false; |
|---|
| 158 | audio = false; |
|---|
| 159 | for(var i=0; i<feed.length; i++) { |
|---|
| 160 | feed[i]["file"] = prefix+feed[i]["file"]; |
|---|
| 161 | if(feed[i]["image"]) { feed[i]["image"] = prefix+feed[i]["image"]; } |
|---|
| 162 | if(feed[i]["link"]) { feed[i]["link"] = prefix+feed[i]["link"]; } |
|---|
| 163 | if(stream != undefined) { |
|---|
| 164 | if(feed[i]["type"] == "rtmp") { |
|---|
| 165 | feed[i]["id"] += stream; |
|---|
| 166 | feed[i]["file"] = feed[i]["file"]; |
|---|
| 167 | } else if(feed[i]["type"] == "flv") { |
|---|
| 168 | feed[i]["file"] = |
|---|
| 169 | feed[i]["file"].substr(0,feed[i]["file"].length-4) + |
|---|
| 170 | stream + feed[i]["file"].substr(-4); |
|---|
| 171 | } |
|---|
| 172 | } |
|---|
| 173 | if(feed[i]["type"] != "mp3") { onlymp3s = false; } |
|---|
| 174 | if(feed[i]["start"] == undefined) { feed[i]["start"] = 0; } |
|---|
| 175 | if(feed[i]['file'] != feed[0]['file']) { ischapters = false; } |
|---|
| 176 | if(feed[i]["captions"] != undefined) { captions = true; } |
|---|
| 177 | if(feed[i]["audio"] != undefined) { audio = true; } |
|---|
| 178 | if(feed[i]['duration'] == undefined || isNaN(feed[i]['duration'])){ |
|---|
| 179 | feed[i]['duration'] = 0; |
|---|
| 180 | } |
|---|
| 181 | if(feed[i]['fallback'] != undefined) { |
|---|
| 182 | var maj = Number(System.capabilities.version.split(' ')[1].substr(0,1)); |
|---|
| 183 | var min = Number(System.capabilities.version.split(',')[2]); |
|---|
| 184 | if(maj < 9 || (maj == 9 && min < 90)) { |
|---|
| 185 | feed[i]['file'] = feed[i]['fallback']; |
|---|
| 186 | } |
|---|
| 187 | } |
|---|
| 188 | } |
|---|
| 189 | updateListeners('new'); |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | |
|---|
| 193 | /** Return the lenght of the feed array. **/ |
|---|
| 194 | public function getLength():Number { |
|---|
| 195 | return feed.length; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | /** Add an item to the feed **/ |
|---|
| 200 | public function addItem(obj:Object,idx:Number) { |
|---|
| 201 | if(obj['title'] == undefined) { obj['title'] = obj['file']; } |
|---|
| 202 | if(obj['type'] == undefined) { obj['type'] = obj['file'].substr(-3); } |
|---|
| 203 | if(arguments.length == 1 || idx >= feed.length) { |
|---|
| 204 | feed.push(obj); |
|---|
| 205 | } else { |
|---|
| 206 | var arr1 = feed.slice(0,idx); |
|---|
| 207 | var arr2 = feed.slice(idx); |
|---|
| 208 | arr1.push(obj); |
|---|
| 209 | feed = arr1.concat(arr2); |
|---|
| 210 | } |
|---|
| 211 | updateListeners('add'); |
|---|
| 212 | }; |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | /** Remove an item from the feed **/ |
|---|
| 216 | public function removeItem(idx:Number) { |
|---|
| 217 | if(feed.length == 1) { |
|---|
| 218 | return; |
|---|
| 219 | } else if(arguments.length == 0 || idx >= feed.length) { |
|---|
| 220 | feed.pop(); |
|---|
| 221 | } else { |
|---|
| 222 | feed.splice(idx,1); |
|---|
| 223 | } |
|---|
| 224 | updateListeners('remove'); |
|---|
| 225 | }; |
|---|
| 226 | |
|---|
| 227 | |
|---|
| 228 | /** Retrieve playlist data for a specific item **/ |
|---|
| 229 | public function itemData(idx:Number):Object { |
|---|
| 230 | return feed[idx]; |
|---|
| 231 | }; |
|---|
| 232 | |
|---|
| 233 | |
|---|
| 234 | /** Add a feed update listener. **/ |
|---|
| 235 | public function addListener(lst:Object) { |
|---|
| 236 | listeners.push(lst); |
|---|
| 237 | }; |
|---|
| 238 | |
|---|
| 239 | |
|---|
| 240 | /** Remove a feed update listener. **/ |
|---|
| 241 | public function removeListener(lst:Object) { |
|---|
| 242 | for(var i = listeners.length; --i >= 0; ) { |
|---|
| 243 | if(listeners[i] == lst) { |
|---|
| 244 | listeners.splice(i,1); |
|---|
| 245 | return; |
|---|
| 246 | } |
|---|
| 247 | } |
|---|
| 248 | }; |
|---|
| 249 | |
|---|
| 250 | |
|---|
| 251 | /** Notify all listeners of a feed update **/ |
|---|
| 252 | private function updateListeners(typ:String) { |
|---|
| 253 | for(var i = listeners.length; --i >= 0; ) { |
|---|
| 254 | listeners[i].onFeedUpdate(typ); |
|---|
| 255 | } |
|---|
| 256 | }; |
|---|
| 257 | |
|---|
| 258 | |
|---|
| 259 | } |
|---|