Message to marc2k3:
I have Columns UI and JScriptPanel3 3.4.10 installed and have configured "Track Info + Seekbar + Buttons + Volume.txt" with my own code.
I need, if possible, the following:
In the image you can see in the playlist view, the title column in which I have made a script with title formating that makes the texts in parentheses (up to a maximum of 4) except if it is at the beginning to be painted in low brightness.
The caption shows the title with the text in parentheses on the right removed.
What I need is a routine that allows to paint in the footer the title with the texts in brackets that are not at the beginning in low luminosity.
Current:
(I Love You) Caravan
Desired:
(I Love You) Caravan (Bande Originale Du Film) aka "Paris, Paris" (Spain) "Paris 36" (Europe)
// ==PREPROCESSOR==
// @name "Track Info + Seekbar + Buttons + Volume"
// con 1 fuente (Segoe Fluent Icons.ttf)
// Pie en un solo panel
// @author "marc2003"
// @import "%fb2k_component_path%helpers.txt"
// @import "%fb2k_component_path%samples\js\lodash.min.js"
// @import "%fb2k_component_path%samples\js\common.js"
// @import "%fb2k_component_path%samples\js\panel.js"
// @import "%fb2k_component_path%samples\js\seekbar.js"
// @import "%fb2k_component_path%samples\js\volume.js"
// ==/PREPROCESSOR==
/*
The Segoe Fluent Icons font is already included with Windows 11. Windows 10 users can download it here:
https://download.microsoft.com/download/8/f/c/8fc7cbc3-177e-4a22-af48-2a85e1c5bffb/Segoe-Fluent-Icons.zip
If installed, you can right click the panel and change the button set.
*/
//////////////////////////////////////////////////////////////
//tamaño botones
var bs = _scale(26);
var sep_bot = 3;
//tamaño botón volume
var bsv = _scale(25);
//posicion botones
var posi_horiz_bot = -1;
var posi_vert_bot = 757;
//posiciones para el botón activate
var posi_horiz_bot2 = -1;
var posi_vert_bot2 = 275;
//posiciones seekbar
var posi_vert_seekbar_ini = 59;
var ancho_seekbar = _scale(896);
var alto_seekbar = _scale(5);
var posi_horiz_seekbar = 2;
//posiciones knob
var ancho_knob = _scale(6)
var alto_knob = ancho_knob
//posiciones barra volumen
var alto_volume = alto_seekbar;
var posi_horiz_barra_volume = _scale(24);
var ancho_volume = _scale(524);
var separacion_pared_derecha_volume = _scale(13);
//posición icono volumen
var posi_horiz_volume = _scale(14);
//el valor _scale(-xxx) marca el límite en que se corta el texto con ...
var limite1 = _scale(-485);
var posi_vert_lin_izq = 10;
var posi_horiz_lin1 = -5;
var posi_horiz_lin2 = 24;
//Recuadro de tiempos
//desplazamiento vertical
var time_x = 1420
//desplazamiento horizontal
var time_y = 23
//ancho de izq. a dcha.
var time_w = -240
//alto
var time_h = 26
var posi_horiz_time = 0;
var sep_time = 161;
var posi_vert_time_actual = _scale(1815);
var posi_vert_time_resto = posi_vert_time_actual + sep_time;
var posi_vert_time_total = posi_vert_time_resto + sep_time;
var posi_horiz_porcen = -2
//texto encima volumen
var posi_horiz_linea1 = -25;
var posi_vert_herz = 1650;
var posi_vert_codec = 1827;
//texto debajo volumen
var posi_horiz_gain = 22;
var posi_vert_gain = 1827;
//fuentes para los textos
var normal2_font = CreateFontString('Segoe UI', 12);
var normal3_font = CreateFontString('Segoe UI', 13);
var normal4_font = CreateFontString('Segoe UI', 11);
var normal5_font = CreateFontString('Eras ITC', 14);
var normal6_font = CreateFontString('Segoe UI', 8);
var bold_font = CreateFontString('Segoe UI', 12, true);
//aquí se definen los colores
var colours = {
buttons : RGB(220, 220, 220),
background : RGB(34, 34, 34),
artist : RGB(170, 170, 170),
año : RGB(230, 230, 230),
album : RGB(200, 200, 200),
composer : RGB(160, 160, 160),
track : RGB(200, 200, 200),
title : RGB(225, 225, 225),
porcen : RGB(180, 180, 180),
time : RGB(180, 180, 180),
time_total : RGB(220, 220, 220),
time_reborde : RGB(32, 32, 32),
time_recuadro_degra1 : RGB(25, 25, 25),
time_recuadro_degra2 : RGB(50, 50, 50),
gain : RGB(180, 180, 180),
codec : RGB(170, 170, 170),
seekbar_background : RGB(15, 15, 15),
seekbar_progress : RGB(80, 80, 80),
knob : RGB(220, 0, 0),
sac : RGB(196, 30, 35),
};
//aquí se guardan los metadatos que se van a pintar
//metadatos que se depurarán de paréntesis
var tfo_album = fb.TitleFormat('[%album%]');
var tfo_title = fb.TitleFormat('[%title%]');
var tfo_artist = fb.TitleFormat('[%artist%]');
var tfo_genero = fb.TitleFormat('$if($strcmp($cut(%genre%,7),Clásica),$cut(%genre%,7),)');
var panel = new _panel();
var seekbar = new _seekbar(0, 0, 0, 0);
var volume = new _volume(0, 0, 0, 0);
var buttons = new _buttons();
var img = null;
window.MaxHeight = _scale(150);
on_playback_new_track(fb.GetNowPlaying());
buttons.update = function () {
var y = (Math.round((panel.h - bs) / 2)) + posi_horiz_bot;
// aquí se pintan los botones tomándolos de helpers.txt
this.buttons.stop = new _button(panel.w - posi_vert_bot - (sep_bot * 4) - (bs * 8), y, bs, bs, { char : chars.stop, colour:fb.StopAfterCurrent ? colours.sac : colours.buttons}, null, function () { fb.Stop(); }, 'Stop');
this.buttons.previous = new _button(panel.w - posi_vert_bot - (sep_bot * 3) - (bs * 7), y, bs, bs, { char : chars.prev, colour:colours.buttons }, null, function () { fb.Prev(); }, 'Previous');
this.buttons.play = new _button(panel.w - posi_vert_bot - (sep_bot * 2) - (bs * 6), y, bs, bs, { char : !fb.IsPlaying || fb.IsPaused ? chars.play : chars.pause, colour:colours.buttons}, null, function () { fb.PlayOrPause(); }, !fb.IsPlaying || fb.IsPaused ? 'Play' : 'Pause');
this.buttons.next = new _button(panel.w - posi_vert_bot-sep_bot - (bs * 5), y, bs, bs, { char : chars.next, colour:colours.buttons }, null, function () { fb.Next(); }, 'Next');
// aquí se pinta el boton activate que está definido en helpers.txt como right
var y = (Math.round((panel.h - bs) / 2)) + posi_horiz_bot2;
this.buttons.activate = new _button(panel.w - posi_vert_bot - (bs * 4), y, bs, bs, { char : chars.right, colour:colours.buttons }, null, function () { fb.RunMainMenuCommand('View/Playlist view/Activate now playing'); }, 'Activate now playing');
// Aquí se pinta el boton volumen
this.buttons.volume = new _button(volume.x - bs, posi_horiz_volume, bsv, bsv, { char : chars.volume, colour:colours.buttons }, null, function () { fb.VolumeMute(); }, 'Mute Volume');
}
function update_album_art(metadb) {
if (img) img.Dispose();
img = null;
if (metadb) {
img = metadb.GetAlbumArt();
}
window.Repaint();
}
function on_mouse_lbtn_down(x, y) {
seekbar.lbtn_down(x, y);
volume.lbtn_down(x, y);
}
function on_mouse_lbtn_up(x, y) {
if (x < panel.h && fb.IsPlaying && img) {
fb.GetNowPlaying().ShowAlbumArtViewer();
return;
}
if (buttons.lbtn_up(x, y)) {
return;
}
if (seekbar.lbtn_up(x, y)) {
return;
}
if (volume.lbtn_up(x, y)) {
return;
}
fb.RunMainMenuCommand('View/Show now playing in playlist');
}
function on_mouse_leave() {
buttons.leave();
}
function on_mouse_move(x, y) {
window.SetCursor(x < panel.h && fb.IsPlaying && img ? IDC_HAND : IDC_ARROW);
if (buttons.move(x, y)) {
return;
}
if (seekbar.move(x, y)) {
return;
}
volume.move(x, y);
}
function on_mouse_rbtn_up(x, y) {
if (buttons.buttons.stop.containsXY(x, y)) {
fb.StopAfterCurrent = !fb.StopAfterCurrent;
} else {
var menu = window.CreatePopupMenu();
menu.AppendMenuItem(MF_STRING, 1, 'Configure');
var idx = menu.TrackPopupMenu(x, y);
menu.Dispose();
switch (idx ) {
case 1:
window.ShowConfigure();
break;
}
}
return true;
}
function on_mouse_wheel(s) {
if (seekbar.wheel(s)) {
return;
}
volume.wheel(s);
}
function on_paint(gr) {
//aquí se pinta el background de todo el pie
gr.Clear(colours.background);
//aquí se pinta la barra nula
gr.FillRoundedRectangle(seekbar.x, seekbar.y, seekbar.w + _scale(6), seekbar.h, _scale(2), _scale(2), colours.seekbar_background);
buttons.paint(gr);
//Aquí se pinta la barra de volumen
gr.FillRoundedRectangle(volume.x, volume.y, volume.w + _scale(6), volume.h, _scale(2), _scale(2), colours.seekbar_background)
//aquí se pinta la parte izquierda de la barra de volumen
var pos = volume.pos();
gr.FillRoundedRectangle(volume.x, volume.y, pos, volume.h, _scale(2), _scale(2), colours.seekbar_progress);
//aquí se pinta el knob del volumen
gr.FillEllipse(volume.x + _scale(3) + pos, volume.y + _scale(3), ancho_knob, alto_knob, colours.knob);
buttons.paint(gr);
//aquí se pinta el recuadro con reborde que aloja los tiempos
FillGradientRectangle(gr, time_x, time_y, time_w, time_h, 0, colours.time_recuadro_degra2, colours.time_recuadro_degra1);
//aquí se pinta el reborde del recuadro
DrawRectangle(gr, time_x, time_y, time_w, time_h, colours.time_reborde);
//aquí se pinta la miniatura fuera de If (fb.IsPlaying) para que no se borre al pulsar stop --------
if (img) {
_drawImage(gr, img, 0, 0, panel.h - 2, panel.h - 2, image.centre);
}
if (fb.IsPlaying) {
//aquí se pinta la linea 1 izq: artist, año, album
//elimino el metadato %album% dejándole su $rgb y tb el %artist% solo en la clásica para después añadir el la string lin1 las strings album y artist ya depuradas de ()
var lin1 = fb.TitleFormat('$if($strcmp($cut(%genre%,7),Clásica),$rgb(170,170,170) $rgb(230,230,230)%date% $rgb(170,170,170),$rgb(170,170,170)[%artist%] $rgb(230,230,230)[%date%] $rgb(170,170,170))').Eval();
//elimina texto entre ()
var arr = tfo_album.Eval();
textoFormateado = QuitaTextoEntreParentesis(arr);
var album = textoFormateado
//elimina texto entre ()
var arr = tfo_artist.Eval();
textoFormateado = QuitaTextoEntreParentesis(arr);
var artist = textoFormateado
var genero = tfo_genero.Eval();
//añado a lin1 las strings depuradas de () de forma que DrawColouredText es capaz de aplicar el color definido en fb.TitleFormat
if (genero == 'Clásica') lin1 = album + lin1 + artist;
else lin1 = lin1 + album;
DrawColouredText(gr,lin1, normal2_font, colours.artist, panel.h + posi_vert_lin_izq, posi_horiz_lin1, seekbar.x - panel.h - limite1, panel.h * 0.5, DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//aquí se pinta la linea 2 izq: composer, track, title
var lin2 = fb.TitleFormat('$if($strcmp($cut(%genre%,7),Clásica),$rgb(130,130,130)"$upper(%composer%)" ,)$rgb(150,150,150)[%tracknumber%. ]$rgb(225,225,225)').Eval();
//elimina texto entre ()
var arr = tfo_title.Eval();
textoFormateado = QuitaTextoEntreParentesis(arr);
var title = textoFormateado
var lin2 = lin2 + title
//la linea siguiente es solo para Susi. En ella se pinta el title sin ninguna depuración de paréntesis
//var lin2 = fb.TitleFormat('$if($strcmp($cut(%genre%,7),Clásica),$rgb(130,130,130)"$upper(%composer%)" ,)$rgb(150,150,150)[%tracknumber%. ]$rgb(225,225,225)%title%').Eval();
DrawColouredText(gr, lin2, normal2_font, colours.title, panel.h + posi_vert_lin_izq, posi_horiz_lin2, seekbar.x - panel.h - limite1, panel.h * 0.9, DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//aquí se pinta el porcen a la dcha. de la seekbar
var porcen = fb.TitleFormat('$ifgreater(%_time_total_seconds%,0,$div($mul(%_time_elapsed_seconds%,100),%_time_total_seconds%) ٪,LIVE)').Eval();
gr.WriteText(porcen, normal3_font, colours.porcen, seekbar.x + seekbar.w + _scale(12), posi_horiz_porcen, _scale(130), panel.h, DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//tiempo transcurrido
var time_actual = fb.TitleFormat('%playback_time%').Eval();
gr.WriteText(time_actual, normal5_font, colours.time, seekbar.x - _scale(50), posi_horiz_time, posi_vert_time_actual, panel.h, DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//tiempo restante
var time_resto = fb.TitleFormat('[- %playback_time_remaining%]').Eval();
gr.WriteText(time_resto, normal5_font, colours.time, seekbar.x - _scale(50), posi_horiz_time, posi_vert_time_resto, panel.h, DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//tiempo total
var time_total = fb.TitleFormat('[%length%]').Eval();
gr.WriteText(time_total, normal5_font, colours.time_total, seekbar.x - _scale(50), posi_horiz_time, posi_vert_time_total, panel.h, DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//aquí se pinta texto encima del volumen -------------------------
//aquí se pinta los herzios en 2 colores
var str = fb.TitleFormat('$ifgreater(%samplerate%,49000,$rgb(0,210,0),)%samplerate% Hz').Eval();
DrawColouredText(gr, str, normal3_font, colours.codec, seekbar.x, posi_horiz_linea1, posi_vert_herz, panel.h, DWRITE_TEXT_ALIGNMENT_TRAILING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//aquí se pintan: bitrate, codec
var tfo = fb.TitleFormat('%bitrate% k $ext($upper(%_path%))');
var arr = tfo.Eval().split('^^');
gr.WriteText(arr[0], normal3_font, colours.codec, seekbar.x, posi_horiz_linea1, posi_vert_codec, panel.h, DWRITE_TEXT_ALIGNMENT_TRAILING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
//aquí se pinta texto debajo del volumen -------------------------
//aquí se pinta last played y gain
var tfo = fb.TitleFormat('[AGain: %replaygain_album_gain% ]$if($and($strcmp($strstr(%last_played%,-),5),$strcmp($strstr(%last_played%,:),14)),Last Play: $substr(%last_played%,9,10)-$substr(%last_played%,6,7)-$substr(%last_played%,1,4) $substr(%last_played%,12,13):$substr(%last_played%,15,16) ,)[TGain: %replaygain_track_gain%]');
var arr = tfo.Eval().split('^^');
gr.WriteText(arr[0], normal4_font, colours.gain, seekbar.x, posi_horiz_gain, posi_vert_gain, panel.h, DWRITE_TEXT_ALIGNMENT_TRAILING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER, DWRITE_WORD_WRAPPING_NO_WRAP, DWRITE_TRIMMING_GRANULARITY_CHARACTER);
if (fb.PlaybackLength > 0) {
var pos = seekbar.pos();
//aquí se pinta la parte izquierda de la seekbar
gr.FillRoundedRectangle(seekbar.x, seekbar.y, pos, seekbar.h, _scale(2), _scale(2), colours.seekbar_progress);
//aquí se pinta el knob del seekbar avanzando
gr.FillEllipse(seekbar.x + _scale(3) + pos, seekbar.y + _scale(3), ancho_knob, alto_knob, colours.knob);
}
}
}
function on_playback_dynamic_info_track(type) {
if (type == 0) window.Repaint();
else update_album_art(fb.GetNowPlaying());
}
function on_playback_edited() {
window.Repaint();
}
function on_playback_new_track(metadb) {
update_album_art(metadb);
}
function on_playback_pause() {
buttons.update();
window.Repaint();
}
function on_playback_seek() {
seekbar.playback_seek();
}
function on_playback_starting() {
buttons.update();
window.Repaint();
}
function on_playback_stop() {
buttons.update();
window.Repaint();
}
function on_playback_time() {
//la linea siguiente la sustituí por la siguiente según me indicó marc2k3 en el foro para arreglar el que no se pintaban los tiempos per second
// window.RepaintRect(panel.h, 0, seekbar.x - panel.h, panel.h);
window.Repaint();
}
function on_playlist_stop_after_current_changed() {
buttons.update();
window.Repaint();
}
//aquí se definen las coordenadas de la seekbar y el volumen
function on_size() {
panel.size();
seekbar.x = _scale(posi_vert_seekbar_ini);
seekbar.w = panel.w - seekbar.x - ancho_seekbar;
seekbar.h = alto_seekbar;
seekbar.y = (panel.h - seekbar.h) / posi_horiz_seekbar;
volume.x = seekbar.x + seekbar.w + ancho_volume + (bs * 5);
volume.y = posi_horiz_barra_volume;
volume.w = panel.w - volume.x - separacion_pared_derecha_volume;
volume.h = alto_volume;
buttons.update();
}
function on_volume_change() {
volume.volume_change();
window.Repaint();
}
function QuitaTextoEntreParentesis(arr) {
//elimina texto entre () excepto que esté al principio
//1ª depuración empezando por la derecha
var first = arr.indexOf('(');
var last = arr.lastIndexOf('(');
if (last > first) arr = arr.substr(0, last-1).trim();
else if (first > 0) arr = arr.substr(0, first-1).trim();
//2ª depuración empezando por la derecha
var first = arr.indexOf('(');
var last = arr.lastIndexOf('(');
if (last > first) arr = arr.substr(0, last-1).trim();
else if (first > 0) arr = arr.substr(0, first-1).trim();
//3ª depuración empezando por la derecha
var first = arr.indexOf('(');
var last = arr.lastIndexOf('(');
if (last > first) arr = arr.substr(0, last-1).trim();
else if (first > 0) arr = arr.substr(0, first-1).trim();
//4ª depuración empezando por la derecha
var first = arr.indexOf('(');
var last = arr.lastIndexOf('(');
if (last > first) arr = arr.substr(0, last-1).trim();
else if (first > 0) arr = arr.substr(0, first-1).trim();
textoFormateado = arr
return textoFormateado;
}