To hejiame
/*
====================================================================================================
=======
Lyriks 1.0 (build 20101012.0815) - a WSH lyrics module by Br3tt
- This WSH script get lyrics from TAG first then from local file in foobar2000\lyrics\
then it displays them (scrolling)
- It handles TXT and LRC format (sync handled), but not the LRC Enhanced format
(it translates eLRC to a normal LRC text)
- Comments, Blank lines, Info lines are ignored.
- Manual Scrolling possible with the mousewheel (double click on the panel to re-center on the active line)
- Requirements :
1) foobar2000
2) WSH Panel Mod component
3) this script in a WSH panel
4) Optional: a lyrics grabber (i.e: Lyric Show Panel by hidding the panel, foo_lyricsDB, ...)
- Some settings are available by using the panel Properties (right click on WSH panel -> Properties)
- This script don't make any changes to your files and write nothing on your system.
It's just a read&display data script.
====================================================================================================
=======
*/
// Text formatting function
// {{
function StringFormat() {
var h_align = 0,
v_align = 0,
trimming = 0,
flags = 0;
switch (arguments.length) {
// fall-thru
case 4:
flags = arguments[3];
case 3:
trimming = arguments[2];
case 2:
v_align = arguments[1];
case 1:
h_align = arguments[0];
break;
default:
return 0;
}
return ((h_align << 28) | (v_align << 24) | (trimming << 20) | flags);
}
StringAlignment = {
Near: 0,
Centre: 1,
Far: 2
};
var lc_stringformat = StringFormat(StringAlignment.Near, StringAlignment.Centre);
var cc_stringformat = StringFormat(StringAlignment.Centre, StringAlignment.Centre);
var rc_stringformat = StringFormat(StringAlignment.Far, StringAlignment.Centre);
// }}
//{{
// IO Mode
var ForReading = 1;
var ForWriting = 2;
var ForAppending = 8;
//}}
//{{
// Paths
var metadb = fb.IsPlaying ? fb.GetNowPlaying() : false;
if (metadb){
var lyrics_dir = fb.Titleformat("$replace($replace(%path%,%filename_ext%,),\,\\)").EvalWithMetadb(metadb);
}
else{
var lyrics_dir = "C:\\"
}
//fb.trace(lyrics_dir);
lyrics_folder_exists();
//}}
//{{
// new object
sentence = function () {
this.type = null;
this.timer = 0;
this.text = "";
this.total_lines = 0;
this.ante_lines = 0;
}
//}}
function RGBA(r, g, b, a) {
return ((a << 24) | (r << 16) | (g << 8) | (b));
}
// ================================================/ TF
var len_seconds = fb.Titleformat("%length_seconds%");
var elap_seconds = fb.TitleFormat("%playback_time_seconds%");
var artist = fb.Titleformat("$replace(%artist%,'/','_')");
var title = fb.Titleformat("%title%");
var lyrics = fb.TitleFormat("[$if2(%LYRICS%,$if2(%LYRIC%,$if2(%UNSYNCED LYRICS%,%UNSYNCED LYRIC%)))]");
// ================================================/ Declarations
var g_font = gdi.Font("segoe ui", 12, 0);
var g_playtimer;
var ww = 0,
wh = 0;
var g_fso = new ActiveXObject("Scripting.FileSystemObject");
var g_file = null;
var g_tab = Array();
var g_scroll = 0;
var g_lyrics_filename;
var g_lyrics_status;
var focus = 0;
var focus_next = 0;
var g_plainbg_colour;
var g_ovbg_normalcolour;
var g_ovbg_highlightcolour;
var g_txt_normalcolour;
var g_txt_highlightcolour;
var g_txt_shadowcolour;
var centiemes = 0;
var g_is_scrolling = false;
var g_multi_balise = false;
var g_balise_total;
var g_balise_char_offset;
var g_tab_length;
var midpoint;
var pos;
// ================================================/ Settings
var PLAYTIMER_VALUE = window.GetProperty("Timer value in ms [10;100]", 10);
var LINE_HEIGHT = window.GetProperty("Line height [20;30]", 24);
var TEXT_SHADOW = window.GetProperty("Text shadow (true/false)", true);
var PLAIN_COLOR_BG = window.GetProperty("Plain colour background (true/false)", false);
var DITHER = window.GetProperty("Top & Botom dither (true/false)", true);
var H_PADDING = window.GetProperty("Horizontal padding [0;20]", 20);
var TXT_ALIGN = window.GetProperty("Text alignment (left/center/right)", "center");
var LIGHT_BG = window.GetProperty("Light background", true);
var DEBUG = false;
var DEFAULT_OFFSET = 29;
// START
function on_size() {
var k;
ww = window.Width;
wh = window.Height;
// exit test on useless calls made (wsh tweak)
if (!ww && !wh) return true;
midpoint = wh / 2 - LINE_HEIGHT / 2;
// colours
g_plainbg_colour = RGBA(140, 200, 250, 255);
g_ovbg_normalcolour = RGBA(000, 000, 000, 130);
g_ovbg_highlightcolour = RGBA(020, 100, 240, 130);
g_txt_normalcolour = RGBA(200, 200, 210, 255);
g_txt_highlightcolour = RGBA(255, 255, 255, 255);
g_txt_shadowcolour = RGBA(000, 000, 000, 150);
g_playtimer && window.KillTimer(g_playtimer);
if (fb.IsPlaying || fb.IsPaused) {
g_scroll = 0;
g_is_scrolling = false;
get_lyrics();
change_focus();
k = g_tab[focus].ante_lines * LINE_HEIGHT;
if (g_lyrics_status > 0) {
pos = midpoint - k;
g_playtimer = window.CreateTimerInterval(PLAYTIMER_VALUE);
} else {
delta = (g_tab[g_tab.length - 1].ante_lines + g_tab[g_tab.length - 1].total_lines);
pos = (wh / 2) - (delta * LINE_HEIGHT / 2);
}
}
}
function on_paint(gr) {
PLAIN_COLOR_BG && gr.FillSolidRect(0, 0, ww, wh, g_bgcolour);
if (fb.IsPlaying || fb.IsPaused) {
show_lyrics(gr, g_tab, pos);
DEBUG && gr.GdiDrawText(g_lyrics_status.toString(), g_font, g_normalcolour, 5, 5, ww, LINE_HEIGHT, DT_TOP | DT_LEFT | DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
}
DITHER && gr.FillGradRect(0, 0, ww, 11, 90, g_txt_shadowcolour, RGBA(0, 0, 0, 0));
DITHER && gr.FillGradRect(0, wh - 11, ww, 11, 270, g_txt_shadowcolour, RGBA(0, 0, 0, 0));
}
function on_mouse_lbtn_dblclk(x, y, mask) {
on_size();
}
function on_mouse_leave() {
window.Repaint();
}
function on_playback_time(time) {
// at each new seconde, centiemes is reset to 0 (Increment on timer every 100ms)
centiemes = 0;
if (g_lyrics_status == 0) {
if (elap_seconds.Eval() == 3) {
on_size();
}
window.Repaint();
}
}
function on_playback_new_track(info) {
g_playtimer && window.KillTimer(g_playtimer);
pos = 0;
g_scroll = 0;
g_is_scrolling = false;
metadb = fb.IsPlaying ? fb.GetNowPlaying() : false;
lyrics_dir = fb.Titleformat("$replace($replace(%path%,%filename_ext%,),\,\\)").EvalWithMetadb(metadb);
get_lyrics();
change_focus();
if (g_lyrics_status > 0) {
g_playtimer = window.CreateTimerInterval(PLAYTIMER_VALUE);
}
// fb.trace(lyrics_dir);
}
function on_playback_seek(time) {
var k;
if (g_lyrics_status > 0) {
g_scroll = 0;
g_is_scrolling = false;
change_focus();
k = g_tab[focus].ante_lines * LINE_HEIGHT;
pos = midpoint - k;
window.Repaint();
}
}
function on_playback_stop(reason) {
g_playtimer && window.KillTimer(g_playtimer);
if (reason == 0) {
// Stop
window.Repaint();
}
}
function on_mouse_wheel(delta) {
if (g_lyrics_status > 0) {
if (delta > 0) {
pos = (pos >= midpoint) ? pos : pos + LINE_HEIGHT;
} else {
pos = (pos <= (wh / 2 - g_tab_length * LINE_HEIGHT)) ? pos : pos - LINE_HEIGHT;
}
window.Repaint();
}
}
function on_timer(id) {
var t1 = elap_seconds.Eval() * 100 + centiemes;
var t2 = len_seconds.Eval() * 100;
var p1, p2;
if (t1 > t2 - 100) {
g_playtimer && window.KillTimer(g_playtimer);
}
if (g_playtimer) {
if (g_playtimer.ID == id) {
if (!g_is_scrolling && t1 >= g_tab[focus_next].timer) {
p1 = g_tab[focus].ante_lines * LINE_HEIGHT;
p2 = g_tab[focus_next].ante_lines * LINE_HEIGHT;
g_scroll = p2 - p1;
change_focus();
g_is_scrolling = true;
}
if (g_scroll > 0) {
pos--;
g_scroll--;
window.Repaint();
} else {
g_is_scrolling = false;
}
centiemes = (centiemes > 98) ? 0 : (centiemes + 1);
}
}
}
function show_lyrics(gr, tab, posy) {
var i, k;
var text_colour;
var txt_align;
gr.SetTextRenderingHint(5);
gr.SetSmoothingMode(2);
switch (TXT_ALIGN.toUpperCase()) {
case "LEFT":
txt_align = lc_stringformat;
break;
case "CENTER":
txt_align = cc_stringformat;
break;
case "RIGHT":
txt_align = rc_stringformat;
break;
default:
txt_align = cc_stringformat;
}
if (g_lyrics_status > 0) {
if (posy >= 0) {
LIGHT_BG && gr.FillSolidRect(0, Math.floor(posy - wh / 2), ww, Math.floor(wh / 2), g_ovbg_normalcolour);
}
} else {
LIGHT_BG && gr.FillSolidRect(0, 0, ww, wh, g_ovbg_normalcolour);
}
for (i = 0; i < tab.length; i++) {
if (Math.round(posy) >= (LINE_HEIGHT * -4) && Math.round(posy) < wh) {
if (i == focus && g_lyrics_status == 1) {
text_colour = g_txt_highlightcolour;
} else {
if (g_lyrics_status == 0) {
text_colour = g_txt_highlightcolour;
} else {
text_colour = g_txt_normalcolour;
}
}
if (g_lyrics_status > 0) {
LIGHT_BG && gr.FillSolidRect(0, Math.floor(posy), ww, (tab[i].total_lines * LINE_HEIGHT - 0), (i == focus && tab[i].text.length > 1 && g_lyrics_status == 1) ? g_ovbg_highlightcolour : g_ovbg_normalcolour);
}
TEXT_SHADOW && gr.DrawString(tab[i].text, g_font, g_txt_shadowcolour, 1 + H_PADDING, Math.floor(posy) + 0, ww - H_PADDING * 2, (tab[i].total_lines * LINE_HEIGHT), txt_align);
TEXT_SHADOW && gr.DrawString(tab[i].text, g_font, g_txt_shadowcolour, 1 + H_PADDING, Math.floor(posy) + 1, ww - H_PADDING * 2, (tab[i].total_lines * LINE_HEIGHT), txt_align);
gr.DrawString(tab[i].text, g_font, text_colour, 0 + H_PADDING, Math.floor(posy), ww - H_PADDING * 2, (tab[i].total_lines * LINE_HEIGHT), txt_align);
}
posy = Math.floor(posy + LINE_HEIGHT + ((tab[i].total_lines - 1) * LINE_HEIGHT));
}
if (g_lyrics_status > 0 && posy <= wh) {
LIGHT_BG && gr.FillSolidRect(0, Math.floor(posy), ww, Math.floor(wh), g_ovbg_normalcolour);
}
}
function grab_timer(tab, str, count, timer_prec, balise) {
var tminutes, tsecondes, tcentiemes;
var balise_type = -1;
var i;
var redo = 0;
var f_sentence = new sentence;
var b = balise - 1;
while (balise_type < 0) {
if (g_lyrics_status == 1 && balise > 0) {
if (str.substring(0, 1) == "[") {
tminutes = str.substring(1 + (b * g_balise_char_offset), 3 + (b * g_balise_char_offset));
tsecondes = str.substring(4 + (b * g_balise_char_offset), 6 + (b * g_balise_char_offset));
// balise type test [99:99] or [99:99.99]
if (str.substring(6, 7) == "]") {
balise_type = 1;
tcentiemes = 0;
} else {
balise_type = 2;
tcentiemes = str.substring(7 + (b * g_balise_char_offset), 9 + (b * g_balise_char_offset));
}
switch (str.substring(1, 2)) {
case "0":
f_sentence.type = "ly";
f_sentence.timer = Math.round(tminutes) * 60 * 100 + Math.round(tsecondes) * 100 + Math.round(tcentiemes) - DEFAULT_OFFSET;
f_sentence.text = remove_enhanced_balises(str.substring(g_balise_char_offset * g_balise_total, str.length));
break;
case "1":
f_sentence.type = "ly";
f_sentence.timer = Math.round(tminutes) * 60 * 100 + Math.round(tsecondes) * 100 + Math.round(tcentiemes) - DEFAULT_OFFSET;
f_sentence.text = remove_enhanced_balises(str.substring(g_balise_char_offset * g_balise_total, str.length));
break;
case "2":
f_sentence.type = "ly";
f_sentence.timer = Math.round(tminutes) * 60 * 100 + Math.round(tsecondes) * 100 + Math.round(tcentiemes) - DEFAULT_OFFSET;
f_sentence.text = remove_enhanced_balises(str.substring(g_balise_char_offset * g_balise_total, str.length));
break;
case "3":
f_sentence.type = "ly";
f_sentence.timer = Math.round(tminutes) * 60 * 100 + Math.round(tsecondes) * 100 + Math.round(tcentiemes) - DEFAULT_OFFSET;
f_sentence.text = remove_enhanced_balises(str.substring(g_balise_char_offset * g_balise_total, str.length));
break;
default:
// technical info (not displayed)
f_sentence.type = null;
f_sentence.timer = 0;
f_sentence.text = "";
}
} else {
// no balise ==> line is set as a comment (as a blank line)
if (count == 0) g_lyrics_status = 2;
balise_type = 0;
f_sentence.type = null;
f_sentence.timer = timer_prec;
f_sentence.text = "";
}
} else {
f_sentence.type = "tx";
f_sentence.timer = 0;
// check if it's not finally a synch lyrics (lrc) with some first lines with no timestamp!
if (str.substring(0, 1) == "[") {
// balise type test [99:99] or [99:99.99]
if (str.substring(6, 7) == "]") {
g_lyrics_status = 1;
g_balise_char_offset = 7;
} else if (str.substring(9, 10) == "]") {
g_lyrics_status = 1;
g_balise_char_offset = 10;
} else {
balise_type = 0;
f_sentence.text = str;
}
} else {
balise_type = 0;
f_sentence.text = str;
}
}
redo++;
}
return f_sentence;
}
function load_file(filePath, fileName) {
var tab = Array();
var fline = new sentence;
var count = 0;
var enr = 0;
var str = "";
var balise;
var delta;
g_file = open_file(filePath, fileName, ForReading);
g_balise_shift = 0;
while (!g_file.AtEndOfStream) {
str = g_file.ReadLine();
g_balise_total = 0;
if (g_lyrics_status == 1) {
if (str.substring(0, 1) == "[") {
// balise type test [99:99] or [99:99.99]
if (str.substring(6, 7) == "]") {
g_balise_char_offset = 7;
balise = 0; // b = # of balise
while (str.substring(balise * 7, balise * 7 + 1) == "[") {
balise += 1;
}
} else {
g_balise_char_offset = 10;
balise = 0; // b = # of balise
while (str.substring(balise * 10, balise * 10 + 1) == "[") {
balise += 1;
}
}
g_balise_total = balise;
} else if (enr == 0) {
g_lyrics_status = 2;
g_balise_total = 1;
}
} else {
g_balise_total = 1;
}
if (g_balise_total > 1) g_multi_balise = true;
else g_multi_balise = false;
// str loop for each balise found for it ==> occurs created in the array
for (balise = 1; balise <= g_balise_total; balise++) {
fline = grab_timer(tab, str, count, (count > 0) ? tab[count - 1].timer : 0, balise);
if (fline.type != null) {
tab.push(fline);
count++;
}
}
enr += 1;
}
close_file(g_file);
// if file read is empty, set lyrics as not found to avoid script errors
if (count == 0) {
g_lyrics_status = 0;
g_tab = load_track_info();
delta = (g_tab[g_tab.length - 1].ante_lines + g_tab[g_tab.length - 1].total_lines);
pos = (wh / 2) - (delta * LINE_HEIGHT / 2);
return g_tab;
} else {
// add a default last sentence with a timer maximum (for ease of use focus line search method)
tab.push(new sentence);
tab[count].type = "ly";
tab[count].timer = 9999999;
tab[count].text = "---";
tab[count].total_lines = 1;
tab[count].ante_lines = tab[count - 1].ante_lines + tab[count - 1].total_lines;
return sort_tab(tab);
}
}
function parse_tag(tag) {
var t_tab = Array();
var i, j, count;
j = 0;
for (i = 0; i < tag.length; i++) {
if (tag.charCodeAt(i) == 10) {
t_tab.push(tag.substring(j, i));
j = i + 1;
}
}
return parse_line(t_tab);
}
function parse_line(tagtab) {
var tab = Array();
var fline = new sentence;
var count = 0;
var enr = 0;
var str = "";
var balise;
var delta;
g_balise_shift = 0;
for (enr = 0; enr < tagtab.length; enr++) {
str = tagtab[enr];
g_balise_total = 0;
if (g_lyrics_status == 1) {
if (str.substring(0, 1) == "[") {
// balise type test [99:99] or [99:99.99]
if (str.substring(6, 7) == "]") {
g_balise_char_offset = 7;
balise = 0; // b = # of balise
while (str.substring(balise * 7, balise * 7 + 1) == "[") {
balise += 1;
}
} else {
g_balise_char_offset = 10;
balise = 0; // b = # of balise
while (str.substring(balise * 10, balise * 10 + 1) == "[") {
balise += 1;
}
}
g_balise_total = balise;
} else if (enr == 0) {
g_lyrics_status = 2;
g_balise_total = 1;
}
} else {
g_balise_total = 1;
}
if (g_balise_total > 1) g_multi_balise = true;
else g_multi_balise = false;
// str loop for each balise found for it ==> occurs created in the array
for (balise = 1; balise <= g_balise_total; balise++) {
fline = grab_timer(tab, str, count, (count > 0) ? tab[count - 1].timer : 0, balise);
if (fline.type != null) {
tab.push(fline);
count++;
}
}
}
// if file read is empty, set lyrics as not found to avoid script errors
if (count == 0) {
g_lyrics_status = 0;
g_tab = load_track_info();
delta = (g_tab[g_tab.length - 1].ante_lines + g_tab[g_tab.length - 1].total_lines);
pos = (wh / 2) - (delta * LINE_HEIGHT / 2);
return g_tab;
} else {
// add a default last sentence with a timer maximum (for ease of use focus line search method)
tab.push(new sentence);
tab[count].type = "ly";
tab[count].timer = 9999999;
tab[count].text = "---";
tab[count].total_lines = 1;
tab[count].ante_lines = tab[count - 1].ante_lines + tab[count - 1].total_lines;
return sort_tab(tab);
}
}
function load_track_info() {
var tab = Array(new sentence, new sentence, new sentence, new sentence);
var count = 0;
tab[count].type = "tx";
tab[count].text = "---";
count++;
tab[count].type = "tx";
tab[count].text = artist.Eval();
count++;
tab[count].type = "tx";
tab[count].text = title.Eval();
count++;
tab[count].type = "tx";
tab[count].text = "---";
count++;
return calc_lines(tab);
}
function open_file(filePath, fileName, ioMode) {
var fileInst = null;
var bool = file_exists(filePath + fileName);
if (bool) {
fileInst = g_fso.OpenTextFile(filePath + fileName, ioMode);
}
return fileInst;
}
function close_file(fileInst) {
fileInst.Close();
}
function read_file(fileInst) {
var line = fileInst.ReadLine();
return line;
}
function folder_exists(folderPath) {
var fso, bool;
fso = new ActiveXObject("Scripting.FileSystemObject");
bool = fso.FolderExists(folderPath);
return bool;
}
function file_exists(filePath) {
var fso, bool;
fso = new ActiveXObject("Scripting.FileSystemObject");
bool = fso.Fileexists(filePath);
return bool;
}
function lyrics_folder_exists() {
var fso;
var bool = 1;
fso = new ActiveXObject("Scripting.FileSystemObject");
if (folder_exists(lyrics_dir) == false) {
fso.CreateFolder(lyrics_dir);
bool = 0;
}
return bool;
}
function get_lyrics() {
var i = 0;
var nbl = 0;
var delta;
var tag;
var bool_tag = false;
// reset lyrics tab
g_lyrics_status = 0;
if (g_tab.length > 0) g_tab.splice(0, g_tab.length);
pos = midpoint;
focus = 0;
window.Repaint();
// check TAGs
tag = lyrics.Eval();
if (tag.length > 0) {
bool_tag = true;
if (tag.substring(0, 1) == "[") g_lyrics_status = 1;
else g_lyrics_status = 2;
} else {
// check files
g_lyrics_filename = artist.Eval() + " - " + title.Eval();
if (file_exists(lyrics_dir + g_lyrics_filename + ".lrc")) {
g_lyrics_filename = g_lyrics_filename + ".lrc";
g_lyrics_status = 1;
} else {
if (file_exists(lyrics_dir + g_lyrics_filename + ".txt")) {
g_lyrics_filename = g_lyrics_filename + ".txt";
g_lyrics_status = 2;
} else {
g_lyrics_status = 0;
}
}
}
// if lyrics found
if (g_lyrics_status > 0) {
if (bool_tag) {
g_tab = parse_tag(tag);
} else {
g_tab = load_file(lyrics_dir, g_lyrics_filename);
}
// console dump of the memory tab loaded
if (g_lyrics_status > 0) {
for (i = 0; i < g_tab.length; i++) {
//fb.trace("line #"+i+" = "+g_tab[i].text + " / "+g_tab[i].timer + " / "+g_tab[i].total_lines + " / "+g_tab[i].ante_lines);
}
}
} else {
g_tab = load_track_info();
// console dump of the memory tab loaded
for (i = 0; i < g_tab.length; i++) {
//fb.trace("line #"+i+" = "+g_tab[i].text + " / "+g_tab[i].timer + " / "+g_tab[i].total_lines + " / "+g_tab[i].ante_lines);
}
delta = (g_tab[g_tab.length - 1].ante_lines + g_tab[g_tab.length - 1].total_lines);
pos = (wh / 2) - (delta * LINE_HEIGHT / 2);
}
if (g_lyrics_status == 2) {
for (i = 0; i < g_tab.length - 1; i++) {
g_tab[i].timer = i * Math.floor(len_seconds.Eval() * 100 / g_tab.length);
}
}
}
function change_focus() {
var i, j;
var t1 = elap_seconds.Eval() * 100 + centiemes;
if (g_lyrics_status > 0) {
// search line index just after actual timer
for (i = 0; i < g_tab.length; i++) {
if (g_tab[i].timer > t1) break;
}
focus_next = i;
focus = (i > 0) ? i - 1 : 0;
// now i check if there are more than one line with the same timer as focus one & if found, i take it as new focus 'cause it's the first (not a blank line)
if (focus > 0) {
for (i = 0; i < focus; i++) {
if (g_tab[i].timer == focus) {
focus = i;
break;
}
}
}
}
}
function calc_lines(ctab) {
var i, j;
var padx = 0;
g_tab_length = 0;
for (i = 0; i < ctab.length; i++) {
// calc sentence #lines to display / window.width
if (ctab[i].type != null) {
var tmp_img = gdi.CreateImage(ww - (H_PADDING * 2) - padx, 100);
var gp = tmp_img.GetGraphics();
var lineh = gp.MeasureString(ctab[i].text, g_font, 0, 0, ww - (H_PADDING * 2) - padx, wh).Height;
ctab[i].total_lines = (lineh / LINE_HEIGHT) > Math.floor(lineh / LINE_HEIGHT) ? Math.floor(lineh / LINE_HEIGHT) + 1 : Math.floor(lineh / LINE_HEIGHT);
ctab[i].ante_lines = 0;
for (j = 0; j < i; j++) {
ctab[i].ante_lines += ctab[j].total_lines;
}
CollectGarbage();
}
g_tab_length += ctab[i].total_lines;
}
return ctab;
}
function sort_tab(tab2sort) {
var tab = Array();
var i, j;
var tmp = new sentence;
var smallest = 0;
for (i = 0; i < tab2sort.length; i++) {
for (j = i; j < tab2sort.length; j++) {
if (tab2sort[i].timer > tab2sort[j].timer) {
tmp = tab2sort[i];
tab2sort[i] = tab2sort[j];
tab2sort[j] = tmp;
}
}
tab.push(tab2sort[i]);
}
tab = calc_lines(tab);
return tab;
}
function remove_enhanced_balises(str) {
var i;
var chr1, chr2;
var new_str = "";
for (i = 0; i < str.length; i++) {
chr1 = str.substring(i, i + 1);
if (i + 10 <= str.length) chr2 = str.substring(i + 9, i + 10);
else chr2 = null;
if (chr1 == "<" && chr2 == ">") {
i = i + 9;
} else {
new_str = new_str + chr1;
}
}
return new_str;
}