raismth.ns(function() { with (raismth.LIB) {
myDump("[RAISMTH] utils module initialization\n");

theApp.utils =
{
        bypassNTP : function(chan) {
                let year = (new Date()).getFullYear();
                let day = raismth.utils.padString((new Date()).getDate());
                let month = raismth.utils.padString((new Date()).getMonth());
                let hour = raismth.utils.padString((new Date()).getHours());
                let min = raismth.utils.padString((new Date()).getMinutes());
                let sec = raismth.utils.padString((new Date()).getSeconds());
                let rnd1 = raismth.auth.rand(0, 1234);
                let rnd2 = raismth.auth.rand(0, 1234);
                let tokenstring = year + ';' + chan + ';' + day + '-' + month + '-' + rnd1 + '-' + hour + '-' + min + '-' + sec + '-' + rnd2;
                let ttauth = raismth.auth.encode3(raismth.auth.encode2(raismth.auth.encode1(tokenstring), 'hMrxuE2T8V0WRW0VmHaKMoFwy1XRc+hK7eBX2tTLVTw='));
                return ttauth;
        },

        addslashes : function(string) {
                return string.replace(/\\/g, '\\\\').
                        replace(/\u0008/g, '\\b').
                        replace(/\t/g, '\\t').
                        replace(/\n/g, '\\n').
                        replace(/\f/g, '\\f').
                        replace(/\r/g, '\\r').
                        replace(/'/g, '\\\'').
                        replace(/"/g, '*');
        },

        go : function(uri){
		window.open(uri, "", "chrome"); 
	},
	
	display_prefs : function() {
		window.openDialog("chrome://raismth/content/options.xul", "raismth-preferences", "chrome,titlebar,toolbar,centerscreen", this);
	},

	get_temp : function() {
		let temp = false;
		try{
			temp = Cc["@mozilla.org/file/directory_service;1"].
			getService(Ci.nsIProperties).
			get("TmpD", Ci.nsILocalFile);
		} catch (e) {
			alert('[RAISMTH] Unable to fetch Temp folder: ' + e);
		} finally {
			// temp = temp.path;
		}

		return temp;
	},
	
	check_deps : function() {
		let Prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
		let deps_bin = { "mplayer":"extensions.raismth.smth-player-path","faad":"extensions.raismth.audio-decoder-path", "mkfifo":"extensions.raismth.mkfifo-bin-path" };
		let deps_bin_desc = { "mplayer":"Mplayer\n[http://www.mplayerhq.hu/]", "faad":"Faad decoder\n[http://www.audiocoding.com/]", "mkfifo":"mkfifo executable" };
		for(var key in deps_bin) {
			let path = Prefs.getCharPref(deps_bin[key]);
			let basepath = false;
			let name = key;
			if(path != '') {
				basepath = path.substring(0, path.lastIndexOf('/') + 1);
				name = path.replace(basepath, '');
			}
			let search = raismth.utils._locate_file(name,basepath,true);
			if(!search) search = raismth.utils._locate_file(name,false,true);
			if(search) {
				raismth.features[key] = search.path;
				if(search.path != path) { 
					Prefs.setCharPref(deps_bin[key], search.path);					
				}
			} else {
				alert('[RAISMTH dependencies check]\n\nDependencies check failed for ' + deps_bin_desc[key]);
				raismth.features[key] = false;
			}
		}
		// alert(raismth.silverlight.odump(raismth.features));
	},

	set_os : function () {
		let temp = raismth.utils.get_temp();
		if(!temp) return false;
		if(temp.path.indexOf(':') == -1) {
			// alert('Linux OS detected');
			raismth.sep = "/";
			raismth.temp_folder = temp;
		} else {
			// alert('Windows OS detected');
			raismth.sep = "\\";
			return false;
		}
		return true;
	},

	check_paths : function (aPath) {	
		let success = false;
		if(aPath) {
			let path = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
			try{
				path.initWithPath( aPath );
				success = path;
			} catch(e) {
				success = false;
				// alert(e);
			} 
		}
		return success;
	},			      

	check_pref : function (path, bin){
		let success = false;			      
		if(bin)	{
			if(path.exists() && path.isExecutable()) success = true;
		} else {
			if(path.exists() && path.isWritable()) success = true;
		}
		return success;
	},
		      
        load_prefs : function() {
		let success = true;
		raismth.prefs = Cc["@mozilla.org/preferences-service;1"]
                         .getService(Ci.nsIPrefService)
                         .getBranch("extensions.raismth.");
	        raismth.prefs.QueryInterface(Ci.nsIPrefBranch2);
		raismth.prefs.addObserver("", this, false);
		raismth.x11 = raismth.prefs.getBoolPref("mplayer-x11");
		raismth.wmadmo = raismth.prefs.getBoolPref("mplayer-wmadmo");
		raismth.wintop = raismth.prefs.getBoolPref("mplayer-top");
		raismth.player_aspect = raismth.prefs.getCharPref("mplayer-aspect");
		raismth.fs = raismth.prefs.getBoolPref("mplayer-fs");
		raismth.forks = raismth.prefs.getBoolPref("mplayer-forks");
		raismth.debug = raismth.prefs.getBoolPref("debug");
		raismth.adaptive = raismth.prefs.getBoolPref("adaptive");
		raismth.autoplay = raismth.prefs.getBoolPref("autoplay");
		raismth.playall = raismth.prefs.getBoolPref("playall");
		raismth.ignoreeof = raismth.prefs.getBoolPref("ignoreeof");
		raismth.loglevel = raismth.prefs.getCharPref("loglevel");
		raismth.ntpbypass = raismth.prefs.getBoolPref("ntp-bypass");
		raismth.mplayer_faad = raismth.prefs.getBoolPref("mplayer-faad");
		raismth.skin = raismth.prefs.getCharPref("default-skin");		
		raismth.default_ql = raismth.prefs.getCharPref("default-ql");
		/*
		let chan1 = raismth.prefs.getIntPref("user-chan1");
		if(typeof(chan1) === 'number') raismth.chan[0] = chan1;
		let chan2 = raismth.prefs.getIntPref("user-chan2");
		if(typeof(chan2) === 'number') raismth.chan[1] = chan2;
		let chan3 = raismth.prefs.getIntPref("user-chan3");
		if(typeof(chan3) === 'number') raismth.chan[2] = chan3;
		*/

		let temp_folder = raismth.utils.check_paths(raismth.prefs.getCharPref("smth-player-temp"));
		if(temp_folder && raismth.utils.check_pref(temp_folder, false)) {
			raismth.temp_folder = temp_folder;
		} 
		// raismth.prefs.setComplexValue("smth-player-temp", Ci.nsILocalFile, raismth.temp_folder);

		let mms_player = raismth.utils.check_paths(raismth.prefs.getCharPref("mmsh-player-path"));
		if(mms_player && raismth.utils.check_pref(mms_player, true)) {
			raismth.mms_player = mms_player;
			// raismth.prefs.setComplexValue("mmsh-player-path", Ci.nsILocalFile, raismth.mms_player);
		} else {
			// alert('Plz check your settings about mms player path\nmplayer, vlc, windows media player, totem...\n\nRaismth How-To:\nhttps://addons.mozilla.org/it/firefox/addon/raismth/');
			// raismth.utils.go('chrome://raismth/content/options.xul');
			raismth.mms_player = false;
			// raismth.utils.display_prefs();
			success = false;
		}

		let smth_player = raismth.utils.check_paths(raismth.prefs.getCharPref("smth-player-path")); 
		if(smth_player && raismth.utils.check_pref(smth_player, true) && smth_player.path.indexOf('mplayer'!=-1)) {
			raismth.smth_player = smth_player;
			// raismth.prefs.setComplexValue("smth-player-path", Ci.nsILocalFile, raismth.smth_player);
		} else {
			raismth.smth_player = false;
			// alert('Plz check your settings about smth player path\nmplayer [http://www.mplayerhq.hu]\n\nRaismth How-To:\nhttps://addons.mozilla.org/it/firefox/addon/raismth/');
			// if(success) raismth.utils.go('chrome://raismth/content/options.xul');
			// if(success) raismth.utils.display_prefs();
			success = false;
		}

		let audio_decoder = raismth.utils.check_paths(raismth.prefs.getCharPref("audio-decoder-path"));
		if(audio_decoder && raismth.utils.check_pref(audio_decoder, true)) {
			raismth.audio_decoder = audio_decoder;
			// raismth.prefs.setComplexValue("audio-decoder-path", Ci.nsILocalFile, raismth.audio_decoder);
		} else {
			raismth.audio_decoder = false;
			// alert('Plz check your settings about audio decoder path\nfaad2 [www.audiocoding.com/faad2.html]\n\nRaismth How-To:\nhttps://addons.mozilla.org/it/firefox/addon/raismth/');
			// if(success) raismth.utils.go('chrome://raismth/content/options.xul');
			// if(success) raismth.utils.display_prefs();
			success = false;
		}
		let mkfifo_bin = raismth.utils.check_paths(raismth.prefs.getCharPref("mkfifo-bin-path"));
		if(mkfifo_bin && raismth.utils.check_pref(mkfifo_bin, true)) {
                        raismth.mkfifo_bin = mkfifo_bin;
		} else {
			// alert('Plz check your settings about mkfifo executable path\nRaismth How-To:\nhttps://addons.mozilla.org/it/firefox/addon/raismth/');
			// if(success) raismth.utils.display_prefs();
			// success = false;
		}
		return success;
        },

        observe: function(subject, topic, data) {
                if (topic != "nsPref:changed")
                {
                        return;
                }
                switch(data)
                {
                        case "mplayer-x11":
                                raismth.x11 = raismth.prefs.getBoolPref("mplayer-x11");
                        break;

			case "mplayer-wmadmo":
				raismth.wmadmo = raismth.prefs.getBoolPref("mplayer-wmadmo");
			break;

                        case "mplayer-top":
                                raismth.wintop = raismth.prefs.getBoolPref("mplayer-top");
                        break;

                        case "mplayer-aspect":
                                raismth.player_aspect = raismth.prefs.getCharPref("mplayer-aspect");
                        break;

                        case "mplayer-fs":
                                raismth.fs = raismth.prefs.getBoolPref("mplayer-fs");
                        break;
			
			case "mplayer-forks":
				raismth.forks = raismth.prefs.getBoolPref("mplayer-forks");
			break;

                        case "mplayer-faad":
                                raismth.mplayer_faad = raismth.prefs.getBoolPref("mplayer-faad");
                        break;

			case "default-skin":
				raismth.skin = raismth.prefs.getCharPref("default-skin");
			break;

			case "default-ql":
				raismth.default_ql = raismth.prefs.getCharPref("default-ql");
			break;
			/*
			case "user-chan1":
		                let chan1 = raismth.prefs.getIntPref("user-chan1");
				if(typeof(chan1) === 'number') raismth.chan[0] = chan1;
			break;

			case "user-chan2":
				let chan2 = raismth.prefs.getIntPref("user-chan2");
				if(typeof(chan2) === 'number') raismth.chan[1] = chan2;
			break;
			
			case "user-chan3":
				let chan3 = raismth.prefs.getIntPref("user-chan3");
				if(typeof(chan3) === 'number') raismth.chan[2] = chan3;
			break;
			*/

                        case "smth-player-temp":
		                let temp_folder = raismth.utils.check_paths(raismth.prefs.getCharPref("smth-player-temp"));
				if(temp_folder && raismth.utils.check_pref(temp_folder, false)) {
					raismth.temp_folder = temp_folder;
					myDump('[RAISMTH] ' + data + ' path fetched\n');
				} else {
					myDump('[RAISMTH] ' + data + ' directory not fetched/writable\n');
				}
                        break;

			case "smth-player-path":
				let smth_player = raismth.utils.check_paths(raismth.prefs.getCharPref("smth-player-path"));
				if(smth_player && raismth.utils.check_pref(smth_player, true) && smth_player.path.indexOf('mplayer'!=-1)) {
					raismth.smth_player = smth_player;
					myDump('[RAISMTH] ' + data + ' path fetched\n');
				} else {
					myDump('[RAISMTH] Plz check your settings about ' + data + '\n');
					raismth.smth_player = false;
				}
			break;

			case "mmsh-player-path":
				let mms_player = raismth.utils.check_paths(raismth.prefs.getCharPref("mmsh-player-path"));
				if(mms_player && raismth.utils.check_pref(mms_player, true)) {
					raismth.mms_player = mms_player;
					myDump('[RAISMTH] ' + data + ' path fetched\n');
				} else {
					myDump('[RAISMTH] Plz check your settings about ' + data + '\n');
					raismth.mms_player = false;
				}
			break;

			case "audio-decoder-path":
				// let audio_decoder = raismth.prefs.getComplexValue("audio-decoder-path", Ci.nsILocalFile);
				let audio_decoder = raismth.utils.check_paths(raismth.prefs.getCharPref("audio-decoder-path"));
				if(audio_decoder && raismth.utils.check_pref(audio_decoder, true)) {
					raismth.audio_decoder = audio_decoder;
					myDump('[RAISMTH] ' + data + ' path fetched\n');
				} else {
					 myDump('[RAISMTH] Make sure the audio decoder (faad2 - www.audiocoding.com/faad2.html) is installed and check your settings about ' + data + '\n');
				}
			break;

			case "mkfifo-bin-path":
				let mkfifo_bin = raismth.utils.check_paths(raismth.prefs.getCharPref("mkfifo-bin-path"));
				if(mkfifo_bin && raismth.utils.check_pref(mkfifo_bin, true)) {
					raismth.mkfifo_bin = mkfifo_bin;
					myDump('[RAISMTH] ' + data + ' path fetched\n');
				} else {
					myDump('[RAISMTH] Make sure mkfifo is installed and check your settings about ' + data + ' path\n');
				}
			break;

                        case "debug":
                                raismth.debug = raismth.prefs.getBoolPref("debug");
                        break;
			
			case "adaptive":
				raismth.adaptive = raismth.prefs.getBoolPref("adaptive");
			break;

			case "autoplay":
				raismth.autoplay = raismth.prefs.getBoolPref("autoplay");
			break;

			case "playall":
				raismth.playall = raismth.prefs.getBoolPref("playall");
				if(!raismth.playall) raismth.prefs.setBoolPref("ignoreeof", false);
			break;

			case "ignoreeof":
				raismth.ignoreeof = raismth.prefs.getBoolPref("ignoreeof");
			break;

			case "loglevel":
				raismth.loglevel = raismth.prefs.getCharPref("loglevel");
			break;

			case "ntp-bypass":
				raismth.ntpbypass = raismth.prefs.getBoolPref("ntp-bypass");
			break;
                }
	},

        goext : function(uri) {
                let opt = false;
		let url = uri.substring(0, uri.indexOf('?'));
		let pattern_1 = uri.indexOf("popup") + 6;
		let pattern_2 = uri.indexOf("&", pattern_1);
		let popup = uri.substring(pattern_1, pattern_2);
		if (popup.toString() == 'true') opt = true; 
		if(opt) { 
	                pattern_1 = uri.indexOf("?");
	                pattern_2 = uri.indexOf("&", pattern_1);
	                let width = uri.substring(pattern_1 + 7, pattern_2);
	                pattern_1 = uri.indexOf("height") + 7;
	                pattern_2 = uri.indexOf("&", pattern_1);
	                let height = uri.substring(pattern_1, pattern_2);
			opt = "menubar=0,resizable=1,width=" + width + ",height=" + height + ",location=0,status=0,scrollbars=1";
			// dump(opt + '\n');
		} else {
			opt = "";
		}

		let a = false;
		if(uri.indexOf("a=") !== -1) a = true;
		if(a === true) window.open(url, "raismth", opt);

        },

	version_check : function (sUrl, fCallback) {
                let now = (new Date()).getDay();
                let lastseen = raismth.prefs.getCharPref("lastseen");
		
		if(lastseen != now) {
			raismth.prefs.setCharPref("lastseen", now);
			raismth.lastseen = "";
			raismth.daily_url = null;
		}
		
		if(raismth.daily_url === null || lastseen != now) {
			let oXHR = new XMLHttpRequest();  
		      	oXHR.onreadystatechange = function() {
			    	if (oXHR.readyState === 4) { fCallback.apply(oXHR); }
		      	};
		      	oXHR.open("GET", sUrl, true);
		      	oXHR.send(null);
		} else {
			fCallback.apply(this);	
		}
		
	},

	showMessage : function () {
		let now = (new Date()).getDay();
		let href = "https://addons.mozilla.org/it/firefox/addon/raismth/";
		if(this.status && this.status === 200) {
			href = this.responseText;
		} else {
			// Not a xhr || xhr failed
		}
		if(raismth.daily_url !== null ) {
			href = raismth.daily_url; // use cached url
		} else {
			raismth.daily_url = href; // set daily url
		}
		
		if(raismth.lastseen === "") {
			raismth.utils.goext(href);
			raismth.lastseen = now;
		}
	},

        wget : function (url, ttauth) {
		myDump('[RAISMTH] wget uri:' + url + ' ttauth: ' + ttauth + '\n');
                raismth.url = url;
                let ioserv = Cc["@mozilla.org/network/io-service;1"]
                        .getService(Ci.nsIIOService);
                let channel = ioserv.newChannel(url, 0, null);
                channel.QueryInterface(Ci.nsIHttpChannel);

                if(ttauth != false){
                        channel.requestMethod = "POST";			
                        channel.setRequestHeader("ttauth", ttauth, false);
                        channel.setRequestHeader("viaurl", "www.rai.tv", false);
                }
                /*
                if(raismth.utf8){
                        channel.setRequestHeader("Content-Type", "text/xml; charset=UTF-8", false);
                        channel.setRequestHeader("Content-Type", "text/xml" + "; charset=UTF-8", false);
                }
                */
                let stream = channel.open();
		try {
			if(!channel.responseStatus) return false;
	                if (channel.responseStatus == 302) return(channel.getResponseHeader('Location'));
			// alert(url);
		
	                if (channel.responseStatus != 200) {
				myDump('[RAISMTH] wget uri:' + url + ' | channel.responseStatus: ' + channel.responseStatus + '\n');
	                        return false;
        	        }
		} catch(e) {
			alert(e);
		} finally {
		
	                // if (channel instanceof Ci.nsIHttpChannel && channel.responseStatus != 200) {
	                //      return "";
	                // }

	                let bstream = Cc["@mozilla.org/binaryinputstream;1"]
	                        .createInstance(Ci.nsIBinaryInputStream);
	                bstream.setInputStream(stream);
	                let size = 0;
	                let file_data = "";
	                while(size = bstream.available()) {
	                        file_data += bstream.readBytes(size);
	                }
	                return file_data;
		}
        },

	_locate_file : function(aName,aPath,x) {
                let nsILocalFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
		let pFile = false;
		let ppath = aPath ? new Array( aPath ) : new Array('/usr/bin/','/usr/sbin/','/usr/local/bin/','/usr/local/sbin/','/bin/','/sbin/');
		for(let c = 0; c < ppath.length; c++) {
			pFile = raismth.utils.check_paths(ppath[c]+aName);
			if(pFile && raismth.utils.check_pref(pFile, x)) {
				break;
			} else {
				pFile = false;
			}
		}
		return pFile;
	},
	
	mkfifo : function(idx) {
		let mkfifobin = raismth.utils._locate_file('mkfifo',false,true);		
		let fifo = 'mplayer-fifo-'+idx;
		let basepath = raismth.temp_folder.path + raismth.sep;
		let ret = raismth.utils._locate_file(fifo,basepath,false);
		if(!mkfifobin && !ret) _FATAL(fifo);
		if(mkfifobin  && !ret) {
			let nsILocalFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
			let nsIProcess = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
			let paramArray = new Array();
                        paramArray.push(basepath+fifo);
			nsIProcess.init(mkfifobin);
			nsIProcess.run(true, paramArray, paramArray.length);
			ret = nsIProcess;
		}
                return ret;
	},

        fifo_init : function(indice){
                let success = false;
                let fifo = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
                try{
                        fifo.initWithPath('/tmp/mplayer-fifo-' + indice);
                } catch(e) {
                        myDump('[RAISMTH] Exception : mplayer-fifo : ' + e + '\n');
                }
                finally {
                        if(fifo.exists()) {
                                myDump('[RAISMTH] Mplayer fifo file detected /tmp/mplayer-fifo-' + indice + '\n');
                                success = fifo;
                        } else {
                                myDump('[RAISMTH] Mplayer fifo file not detected /tmp/mplayer-fifo-' + indice + '\n');
                        }
                }
                return success;
        },

	_pkill : function(idx) {
		// alert('Killing istance #' + idx);
		// let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
		let obj = raismth.slobj[idx];
		let fifo = raismth.mplayer.fifo_init(idx);
		if(obj.playing && fifo) {
			raismth.mplayer.player_control('quit', fifo);
			// timer.initWithCallback(function () {raismth.mplayer.player_control('pause', fifo)}, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
			// raismth.mplayer.player_control('pause', raismth.temp_folder.path + raismth.sep + 'mplayer-fifo-'+idx);		
		} else if(obj.playing && !fifo) {
			obj.pprocess.kill();
		}
	},

	aac_lc_decode : function(infile, sampling) {
		let retvalue = false;				
		let nsILocalFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
                let nsIProcess = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);

                let Prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
		let decoder_path = raismth.audio_decoder.path; 
		// enforce control on player path
                try {
                        nsILocalFile.initWithPath(decoder_path);
                } catch (e) {
                        alert('Check decoder path');
			raismth.sem = false;
                } finally {
                        if(nsILocalFile.exists()){
				let fileout = raismth.temp_folder.path + raismth.sep + infile + '.aac';
				let outlocale = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
				try{
					outlocale.initWithPath(fileout);
					if(outlocale.exists()) {
						outlocale.remove(false);
						myDump('[RAISMTH] ' + fileout + ' removed\n');
					}
				} catch (e) {
					// alert('error');
				} finally {
					// if(outlocale.exists()) outlocale.remove(false);
				}

                                let paramArray = new Array(); 
				paramArray.push(raismth.temp_folder.path + raismth.sep + infile + ".tmp");
		
				if(!raismth.debug) paramArray.push('-q');
				paramArray.push('-l');
				paramArray.push('2');
				paramArray.push('-s');
				paramArray.push(sampling);
				paramArray.push('-a');
				paramArray.push(raismth.temp_folder.path + raismth.sep + infile + ".aac");
				
                                nsIProcess.init(nsILocalFile);
                                nsIProcess.run(true, paramArray, paramArray.length);
                                retvalue = nsIProcess;
				myDump(paramArray.toString() + ' <--- faad cmd line\n');
                        } else {
                                retvalue = false;
                        }
                }
		return retvalue;
  	},
	
	decoder_init : function(outfile, sampling) {
		if(raismth.utils.aac_lc_decode(outfile, sampling)) return true;
		return false;
	},			      
	write_temp : function(data, outfile){
		let target = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
		let path = raismth.temp_folder.path + raismth.sep + outfile + ".tmp";
		target.initWithPath( path );
		try{
			if(target.exists()) {
				target.remove(false);
				myDump('[RAISMTH] ' + path + ' removed\n');
			}
		} catch (e) {
			alert('Error deleting temp file');
		}

		let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
		stream.init(target, 0x04 | 0x08 | 0x20, 0600, 0);
		stream.write(data, data.length);		
		if (stream instanceof Ci.nsISafeOutputStream) {  
			stream.finish();  
		} else {
 			stream.close();  
		}
		myDump('[RAISMTH] Temp Data length: ' + data.length + ' - Outfile: ' + outfile + '.tmp\n');
	},
	read_temp : function(outfile) {
		let ios = Cc["@mozilla.org/network/io-service;1"].
			getService(Ci.nsIIOService);
		let binFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
		binFile.initWithPath( raismth.temp_folder.path + raismth.sep + outfile + ".aac" ) ;
		let istream = Cc["@mozilla.org/network/file-input-stream;1"].  
			              createInstance(Ci.nsIFileInputStream);  
		istream.init(binFile, -1, -1, false);  
		  
		let bstream = Cc["@mozilla.org/binaryinputstream;1"].  
			              createInstance(Ci.nsIBinaryInputStream);  
		bstream.setInputStream(istream);  
		  
		let bytes = bstream.readBytes(bstream.available()); 
		return bytes;
	},
	decode_avc : function(data) {
		let payload = '';
		let size = 0;
		for(let c = 0; c < data.length; c+=size+4) {
			size = raismth.utils.bin2Hex(data.substr(c, 4));
			payload += "\x00\x00\x00\x01" + data.substr(c + 4, size);
		}
		return payload;
	},	 		     
		     
	decode_data : function (data, outfile, idx, clip, video) {
		let slobj = raismth.slobj[idx];
		let decoded = data;
		let media = slobj.myStream;
		let vql_sel = media.vql_sel;
		let aql_sel = media.aql_sel;
		let faad = (media.aFourCC.toLowerCase() === 'aacl') ? true : false;
		let avc  = (media.vFourCC.toLowerCase() === 'avc1' || media.vFourCC.toLowerCase() === 'h264') ? true : false;
		let before = (new Date()).getTime();
		let after = false;
		if(!video && faad && !raismth.mplayer_faad) {
			media = slobj.media.Clip[clip];
			let tgt = media.StreamIndex[media.def_audio_idx];
			let Bitrate = tgt.QualityLevel[aql_sel].Bitrate;
			let SamplingRate = tgt.QualityLevel[aql_sel].SamplingRate;
			// let a = (2 * clip) + 1;
			// let Bitrate = media.stream_index[a][aql_sel].Bitrate;
			// let SamplingRate = media.stream_index[a][aql_sel].SamplingRate;
			raismth.utils.write_temp(data, outfile);
			let success = raismth.utils.decoder_init(outfile, SamplingRate);
			if (success) {
				decoded = raismth.utils.read_temp(outfile);
				raismth.utils.clean_faad_temp_files(outfile);
			} else {
				slobj.stato('DECODER', 'FAAD Decoder timeout FIXME', 0);
			}
			after = (new Date()).getTime();
			slobj.stato('DECODER', 'Faad decoding took ' + (after - before) + ' ms || Decoded data size: ' + decoded.length, 3);
			// Index : 0 || Bitrate : 48000 || CodecPrivateData : || FourCC : AACL || AudioTag : 255 || Channels : 2 || SamplingRate : 48000 || BitsPerSample : 16 || PacketSize : 1
		} else if(video && avc) {
                        decoded = raismth.utils.decode_avc(data);
			after = (new Date()).getTime();
			slobj.stato('DECODER', 'AVC decoding took ' + (after - before) + ' ms || Decoded data size: ' + decoded.length, 3);
                }
                return decoded;
	},

	write_h264_tag : function(outfile, a, h, i) {
		let hdr = raismth.utils.manifest2bin(raismth.utils.h264_header());
		let obj = raismth.slobj[i];
                let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
		if(a) {
			hdr = h;
			stream.init(outfile, 0x02 | 0x10, 0666, 0);
		} else if(obj.bitrate_changed) {
			let cur_hdr = obj.current_hdr;
			hdr = raismth.utils.manifest2bin(cur_hdr);
			obj.bitrate_changed = false;			
			let offset = obj.offset_before;
			stream.init(outfile, 0x04, 0664, 0); 
			let stream_seek = stream.QueryInterface(Ci.nsISeekableStream);
			stream_seek.seek(0x02, 0);
			stream_seek.seek(0x01, offset - stream_seek.tell() );
		} else {
			stream.init(outfile, 0x02, 0666, 0);
		}
                stream.write( hdr, hdr.length );
                stream.close();
                return false;
        },

        write_bin : function(data, outfile, idx, clip, ql, video, h264) {
		let slobj = raismth.slobj[idx];
                if(data) {
			slobj.stato('WRITE-BIN', data.length, 3);
			slobj.decoding = true;
			let decoded = raismth.utils.decode_data(data, outfile, idx, clip, video);
			if(decoded != null) {
                                slobj.stato('WRITE-BIN', 'decoded:' + decoded.length, 3);
                                let target = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
                                let path = raismth.temp_folder.path + raismth.sep + outfile;
                                target.initWithPath( path );
                                let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
				if(h264) h264 = raismth.utils.write_h264_tag(target, false, false, idx);
				if(!h264) {
					stream.init(target, 0x02 | 0x10, 0666, 0);
					stream.write( decoded, decoded.length );
					stream.close();
				}
			}
			slobj.decoding = false;
			return true;
                }
		
		slobj.decoding = false;
                slobj.stato('WRITE-BIN', 'Payload is null: ' + outfile, 0);
                return false;
		
        },

	h264_header : function() {
		let header = 'FF00A101C3D7034F9677';
		return header;
	},

	avc_header : function() {
		let header = '00000001674d401f965605a1afcf80a040000003004000000cb888002dc60000b7187f18e0ed0a15700000000168eacd48';
		return header;
	},

	wave_header : function() {
                let AudioHdr  = "\x52\x49\x46\x46";     // 'RIFF'
                AudioHdr += "\x30\xFF\xFF\xFF";         // chunk size
                AudioHdr += "\x57\x41\x56\x45";         // 'WAVE'
                AudioHdr += "\x66\x6D\x74\x20";         // 'fmt '
                AudioHdr += "\x1C\x00\x00\x00";         // sub chunk size 28
                AudioHdr += "\x61\x01";                 // audio format 353
                AudioHdr += "\x02\x00";                 // num channels 2
                AudioHdr += "\x80\xBB\x00\x00";         // sample rate 48000
                AudioHdr += "\xC0\x5D\x00\x00";         // byte rate 24000 = bit rate 192000
                AudioHdr += "\x00\x20";                 // block size 8192
                AudioHdr += "\x10\x00";                 // bits per sample 16
                AudioHdr += "\x0A\x00";                 // extra param len 10
                AudioHdr += "\x00\x88\x00\x00\x0F\x00\x00\x00\x00\x00"; // extra param = codec private data = 008800000f0000000000
                AudioHdr += "\x64\x61\x74\x61";         // 'data'
                AudioHdr += "\xFF\xFF\xFF\x7F";         // sub chunk size
		return AudioHdr;
	},		

	file_init : function(indice, file_name, file_ext, file_header) {
		let outfile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
		let path = raismth.temp_folder.path + raismth.sep + file_name + file_ext;
		let slobj = raismth.slobj[indice];
		outfile.initWithPath( path );
		try{
			if(outfile.exists()) {
				outfile.remove(false);
				slobj.stato('FILE->INIT', path + ' removed', 3);
			}
			outfile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0666);
		}catch(e){
			slobj.stato('FILE->INIT', 'ERROR: Temp directory access denied: ' + e, 0);
		}finally{
			if(file_header) {
				let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
				stream.init(outfile, 0x02 | 0x08 | 0x10, 0666, 0);
				stream.write(file_header, file_header.length);
				stream.close();
			}
			slobj.stato('FILE->INIT', 'SUCCESS:' + path, 3);
		}		
	},
	
	temp_files_init : function(temp_file, indice, clip, vql, aql) {
                let v_header = false;		
		let a_header = false;
		let v_ext = false;
		let a_ext = false;
		let v = 2 * clip;
		let a = v + 1;
		let slobj = raismth.slobj[indice];
		let media = slobj.media;
		let vqls = new Array();
		let vql_sel = false;
		let aql_sel = false;
		if(clip < media.Clip.length) {
			let tgt = media.Clip[clip];
			let vsi = tgt.StreamIndex[tgt.def_video_idx];
			let svql = vsi.QualityLevel;
			for(let c = 0; c < svql.length; c++) {
				vqls[c] = svql[c].Bitrate;
				if(parseInt(vqls[c]) == parseInt(vql)) vql_sel= c;
			}
			let aqls = new Array();
			let asi = tgt.StreamIndex[tgt.def_audio_idx];
			let asql = asi.QualityLevel;
			for(let c = 0; c < asql.length; c++) {
				aqls[c] = asql[c].Bitrate;
				if(parseInt(aqls[c]) == parseInt(aql)) aql_sel= c;
			}
			let vstream = svql[vql_sel];
			let astream = asql[aql_sel];
			
			let CodecPrivateData = vstream.CodecPrivateData;
			let FourCC = vstream.FourCC;
			if(FourCC.toLowerCase() === 'avc1' || FourCC.toLowerCase() === 'h264') {
				v_header = raismth.utils.manifest2bin(CodecPrivateData);
				// v_ext = FourCC.toLowerCase() === 'avc1' ? '.avc' : '.264';
				v_ext = '.264';
	                } else if(FourCC.toLowerCase() === 'wvc1') {
				v_ext = '.vc1';
			}

			CodecPrivateData = astream.CodecPrivateData;
			FourCC = astream.FourCC;
			if(FourCC.toLowerCase() === 'aacl') {
				if(CodecPrivateData != '') a_header = raismth.utils.manifest2bin(CodecPrivateData);
				a_ext = raismth.mplayer_faad ? '.raw' : '.aac';
	                } else if(FourCC.toLowerCase() === 'wave') {
	                        a_header = raismth.utils.wave_header();
	                        a_ext = '.wav';
	                }
			if(v_ext) 
				raismth.utils.file_init(indice, temp_file, v_ext, v_header);
			else
				slobj.stato('CODEC-INIT', 'Video Codec Not Supported [' + vstream.FourCC + ']', 0);
				
			if(a_ext) 
				raismth.utils.file_init(indice, temp_file, a_ext, a_header);
			else
				slobj.stato('CODEC-INIT', 'Audio Codec Not Supported [' + astream.FourCC + ']', 0);

			let myStream = {};
			myStream.v_ext = v_ext;
			myStream.a_ext = a_ext;
			myStream.vFourCC = vstream.FourCC;
			myStream.aFourCC = astream.FourCC;
			myStream.vql_sel = vql_sel;
			myStream.aql_sel = aql_sel;
			return myStream;
		}
		return false;
	},

	clean_faad_temp_files : function(name) {
		let temp_files = [ '.tmp', '.aac', '.raw' ];
		for (let c = 0; c < temp_files.length; c++) {
			let file_name = raismth.temp_folder.path + raismth.sep + name + temp_files[c];
			myDump('[RAISMTH] ' + file_name + '\n');
			let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
			file.initWithPath( file_name );
			let success = false;
			try{
				if(file.exists()) {
					file.remove(false);
					myDump('[RAISMTH] faad temp file ' + file_name + ' removed\n');
				}
			} catch(e) {
			}
		}
	},

	safe_clean : function(pid,indice) {
		
	},

	clean_temp : function(chan) {
		let temp_files = [ '.vc1', '.wav', '.avc', '.aac', '.raw', '.264' ]; // , '.aac.tmp', '.aac.aac' ];
		for (let c = 0; c < temp_files.length; c++) {
			let file_name = raismth.temp_folder.path + raismth.sep + chan + temp_files[c];
                	let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
			file.initWithPath( file_name );
			let success = false;
			try{
				if(file.exists()) {
					file.remove(false);										
					myDump('[RAISMTH] temp file ' + file_name + ' removed\n');
				}
			} catch(e) {

			}
		}
	},

	getTabIndex : function() {
		let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
			.getService(Ci.nsIWindowMediator);
		let browserEnumerator = wm.getEnumerator("navigator:browser");
		let browserWin = browserEnumerator.getNext();
		let tabbrowser = browserWin.gBrowser;
		let selected = tabbrowser.tabContainer.selectedIndex;
		return selected;
	},

	searchTabs : function(url) {
                let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
                        .getService(Ci.nsIWindowMediator);
                let browserEnumerator = wm.getEnumerator("navigator:browser");
		let found = false;
		while (browserEnumerator.hasMoreElements()) {
			let browserWin = browserEnumerator.getNext();
			let tabbrowser = browserWin.gBrowser;
			let selected = tabbrowser.tabContainer.selectedIndex;
			let numTabs = tabbrowser.browsers.length;
			for (var index = 0; index < numTabs; index++) {
				dump('for: numTabs = ' + numTabs + ' Current:' + index + ' Selected:' + selected + '\n');
				let currentBrowser = tabbrowser.getBrowserAtIndex(index);
				let uri = currentBrowser.currentURI.spec;
				dump('url: ' + url + ' - uri: ' + uri + '\n');
				if(url.toString() == uri.toString()) {
					found = index;
					break;
				}
			}
		}
		return found;
	},
	
        tabselect : function(event) {
                let browser = gBrowser.getBrowserForTab(event.target);
                let uri = browser.currentURI.asciiHost;
                myDump('[RAISMTH] TabSelect event: ' + uri + '\n');
                if (uri.match(/(|www\.)rai\..*/i)){
			// let selected = raismth.utils.getTabIndex();
                        myDump('[RAISMTH] Rai tab selected [Index: ' + selected + ' ]\n');
			// raismth.selected_tab = selected;
                } else {
                        myDump('[RAISMTH] Generic tab selected\n');
                }
        },

	tabClose : function(event) {
		let browser = gBrowser.getBrowserForTab(event.target);
		let uri = browser.currentURI.asciiHost;
		let doc = browser.contentDocument;
		myDump('[RAISMTH] TabClose event: ' + uri + '\n');
		if (uri.match(/(|www\.)rai\..*/i)){
			// let ts = doc.getElementById('raismthWindow').getAttribute('name');
			raismth.utils.purge_arrays(doc);
			mydump('[RAISMTH] tabClose: Rai Tab ' + ts + ' closed\n');
		} else {
			mydump('[RAISMTH] tabClose: Generic Tab closed\n');
		}
		
		/*
		let doc = gBrowser.getBrowserForTab(event.target).contentDocument;
	        let ts = doc.getElementById('raismthWindow').getAttribute('name');
		let indice = raismth.utils.arrayIndexOf(raismth.rai_windows_ts, parseInt(ts));
		myDump('[RAISMTH] tabMonitor - ts:' + ts + ' indice:' + indice + '\n');
		raismth.streams[indice] = null;
		raismth.smthsem[indice] = false;
		raismth.utils.purge_arrays(doc);
		raismth.player_istances[indice].kill();
		*/
	},

        checkRaiTabs : function(){
                let num = gBrowser.browsers.length;
                let res = false;
                for (let i = 0; i < num; i++) {
                        let b = gBrowser.getBrowserAtIndex(i);
                        try {
                                if(b.currentURI.spec.match(/(|www\.)rai\..*/i)) {
                                        myDump('--[RAISMTH] Rai Tab(s) open: ' + b.currentURI.spec + '\n');
                                        res = true;
                                }
                        } catch(e) {
                                Cu.reportError(e);
                                myDump('[RAISMTH] ' + e + '\n');
                        }
                }
                return res;
        },

        IsRaiPage : function(doc) {
		let url = false;
		url = doc.location ? doc.location.href : doc.spec;
		if (url && url.match(/http:\/\/(|www\.)(.*?)rai\..*\/.*/i) && !url.match(/facebook/i) && !url.match(/%3D/i)){			
                // if (doc.location && doc.location.href.match(/http:\/\/(|www\.)rai\..*\/.*/i)){
                        return true;
                } else {
                        return false;
                }
        },

	IsRadio : function(doc) {
		let url = false;
		url = doc.location ? doc.location.href : doc.spec;
		if (url && url.match(/http:\/\/(|www\.)(.*?)rai\..*\/popup\/player_radio.html.*/i) && !url.match(/facebook/i)){
			return true;
		} else {
			return false;
		}
	},

        trim : function(str){
                return str.replace(/^\s+|\s+$/g,"");
        },

        pad : function (str, length) {
                str = '' + str;
                while (str.length < length) {
                        str = str + '\u00A0';
                }
                return str;
        },

// █-----------------------------------------------------------------------------------

	slider : function(pos,max) {
		let ts = '';
		let t = pos*2;
		let h = parseInt(t/3600);
		let m = parseInt((t%3600)/60);
		let s = t-(h*3600)-(m*60);
		if (h) ts = h + 'h ';
		if (m) ts += m + 'm ';
		ts += s + 's';
		let str = '█'; // ' + ts;
		
 		let wsize = 85;
		let step = (wsize/max).toFixed(3);
		max = wsize;
		pos = pos*step;
		while (str.length < max) {
			str = str.length < pos ? " "+str : str+" ";
		}
		let ret = {};
		ret.str = str;
		ret.ts = ts;
		// str += '\n'+ts;
		return ret;
	},

        padString : function(n) {
                let ret = (n<10) ? '0' + n : n;
		return ret;
        },

	bin2Hex : function(s) {
                var i, f = 0;
                var a = [];
                s += '';
                f = s.length;
                for (i = 0; i < f; i++) {
			a[i] = s.charCodeAt(i); // & 0xFF;
			a[i] = a[i].toString(16).replace(/^([\da-f])$/, "0$1");
		}
                var b = a.join('');
                b = parseInt(b, 16);
                return b;
	},

        bin2hex : function(s) {
                var i, f = 0;
                var a = [];
                s += '';
                f = s.length;
                for (i = f - 1; i >= 0; i--) {
                        a[i] = s.charCodeAt(i) & 0xFF;
                        a[i] = a[i].toString(16).replace(/^([\da-f])$/, "0$1");
                }
                var b = a.join('');
                b = parseInt(b, 16);
                return b;
        },

	manifest2bin : function(s) {
		let f = '';
		for(let c = 0; c < s.length; c+=2) {
			f += String.fromCharCode(parseInt(s.substr(c, 2), 16));
		}
		return f;
	},	

        arrayIndexOf : function (array, pattern) {
                let indice; //contatore
                for (indice in array) {
                        if (array[indice] === pattern)
                                return indice;
                }
                return -1;
        },
	
	purge_arrays : function(doc) {
		myDump('[RAISMTH] purge_arrays: ' + raismth.rai_windows_ts.toString() + ' <-ts array before\n');
		myDump('[RAISMTH] purge_arrays: ' + raismth.rai_windows.toString() + ' <-dom array before\n');		
		let ts = doc.getElementById('raismthWindow');
		let ret = false;
		if(ts) {
			ts = ts.getAttribute('name');
			let indice = raismth.utils.arrayIndexOf(raismth.rai_windows_ts, parseInt(ts));
			if(indice != -1){
				ret = indice;
				myDump('[RAISMTH] purge_arrays: myPlayer->stop ts: ' + ts + ' indice: ' + indice + '\n');
				if(raismth.slobj[indice]) raismth.slobj[indice].stop();
				raismth.rai_windows_ts[indice] = 0; 
				raismth.rai_windows[indice] = 0;
				// let old_doc = raismth.rai_windows.splice(indice,1);
				// let old_ts = raismth.rai_windows_ts.splice(indice, 1);
				let Prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
				let rai_windows_counter = Prefs.getIntPref("extensions.raismth.rai_windows_counter");
				rai_windows_counter--;
				myDump('[RAISMTH] purge_arrays: rai_windows_counter: ' + rai_windows_counter + '\n');
				Prefs.setIntPref("extensions.raismth.rai_windows_counter", rai_windows_counter);
				raismth.slobj[indice] = null;
			} else {
				myDump('[RAISMTH] purge_arrays: already purged: ' + ts + '\n');
			}
		}
		myDump('[RAISMTH] purge_arrays: ' + raismth.rai_windows_ts.toString() + ' <-ts array after\n');                      
		myDump('[RAISMTH] purge_arrays: ' + raismth.rai_windows.toString() + ' <-dom array after\n'); 
		return ret;
	},		       
		       
        kill_refresh : function(doc) {
		let jso = myWrapper(doc);
		jso.tryAutoRefresh = function() { };
	},

        setAttr: function(elem, name, value) {
                let i = 0,
                    ntype = elem.nodeType;
 
                // don't set attributes on text, comment and attribute nodes
                if (!elem || ntype === 3 || ntype === 8 || ntype === 2) {
                        return;
                }
 
                if (typeof name === "object") {
                        for (i in name) {
                                raismth.utils.setAttr(elem, i, name[i]);
                        }
                } else {
                        if (value === null) {
                                elem.removeAttribute(name);
                        } else {
                                elem.setAttribute(name, value + "");
                                return value;
                        }
                }
        },
 
        loadCSS: function(doc, elem, file) {
                if (!elem || !file) {
                        return;
                }
 
                let link = doc.createElement("link");
                raismth.utils.setAttr(link, {'rel':'stylesheet', 'type':'text/css', 'href':file});
                elem.appendChild(link);
        },
 
        addClass: function(el, name) {
                if (el.className && el.className.indexOf(name) != -1) { return false; }
 
                el.className += ("" != el.className ? ' ' : '') + name;
        },
 
        removeClass: function(el, name) {
                let p;
                if (!el.className) { return false; }
                if ((p = el.className.indexOf(name)) == -1) { return false; }
 
                el.className = el.className.replace(p ? ' ' + name : name, "");
        },

};

}});
