WSH Panel mod - Scriptbeispiele (Seekbar, Rating, Album-Rating, Coverart & mehr)

Begonnen von TomPro, 16. Juni 2009, 19:24:54

Vorheriges Thema - Nächstes Thema

TomPro

[CUI]

So, meine ersten Gehversuche mit der, für mich, neuen Version von f2k, sind nun schon ein wenig vorangeschritten. Ich konnte viel Anregungen und Codeschnipsel hier aus dem Forum gewinnen und möchte nun deswegen auch den ersten Tribut zollen.

Die grobe Anordnung der einzelnen Module ist nun nach langem hin und her wohl das was am Ende auch Final erhalten bleibt. Einige Funktionsweisen und Ideen dahinter sind aber noch nicht verwirklicht.

Hier ein Screnshot der Oberfläche:
-

Oben links arbeitet ein "Channel Spectrum Panel" und daneben vier "WSH Panel Mod's", alle 5 Module in einem "Panel Stack Splitter". Das erste "WSH Panel Mod" visualisiert den Rating Tag mittels $meta(rating) (fertig), wohingegen das dritte ein Rating anhand der Spielhäufigkeit anzeigen soll (noch nicht fertig). Ob die Ovale bleiben oder noch den üblichen Sternen weichen müssen weiß ich jetzt noch nicht, auch bin ich mit mir noch nicht im Konsens ob die linke Rating-Anzeige sensitiv (Button's zum TAG-schreiben) sein soll.

Ganz rechts außen ist dann noch eine Volume-Seek-Bar mit logarithmischer Kennlinie.


//----------------------------------------------------------------------------
//--- 1stStrike Volumebar (by TomPro)
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//------ Global
//--------- Window
var ww = window.Width;
var wh = window.Height;
var ImgBg = fb.FoobarPath + "1stStrike\\Back\\Volume.png" // Path and Name of Background Image
//--------- Set Color
function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r,g,b,a){ return ((a<<24)|(r<<16)|(g<<8)|(b)); }
//----------------------------------------------------------------------------
//------ Text Options
//--------- Font
// format : x = gdi.Font("FontName", ptSize, F_Style);
var F_Style = 0;
var F_Bold = 1;
var F_Italic = 2;
var F_Underline = 4;
var F_Strikeout = 8;
//--------- Format
//------------ Align
var align_top = 0; var align_middle = 1; var align_bottom = 2;
var align_left = 0; var align_center = 1; var align_right = 2;
//------------ Trim
var trim_no = 0; var trim_chara = 1; var trim_word =2;
var trim_elips_path = 5; var trim_elips_chara = 3; var trim_elips_word =4;
//------------ Flag
var flag_rtl =0x0001;
var flag_vert =0x0002;
var flag_nofit =0x0004;
var flag_dispctrl =0x0020;
var flag_nofallback =0x0400;
var flag_trailspace =0x0800;
var flag_nowrap =0x1000;
var flag_linelimit =0x2000;
var flag_noclip =0x4000;
//------------ Set String Format
function StrFmt(alignH,alignV,trim,flag){
return ((alignH<<28)|(alignV<<24)|(trim<<20)|flag);
}
//----------------------------------------------------------------------------
//------ Volumebar
//--------- Background Image
var BgImg = gdi.Image(ImgBg);
//--------- String Format
var StrFmt_Vol = StrFmt(align_center, align_bottom, trim_no, flag_nowrap | flag_noclip);
//--------- String Color
var StrCo_Vol = RGB(255,255,096);
var StrCo_dB = RGB(160,160,000);
//--------- String Font
var StrFo_Vol = gdi.Font("Arial", 8, F_Style + F_Bold);
var StrFo_dB = gdi.Font("Arial", 9, F_Style + F_Bold);
//--------- Text
var txt_Vol = (Math.ceil(volume));
var txt_dB = ("dB");
//--------- Variable
var volume = fb.Volume;
var pos = wh * (1 - vol2pos(volume));
//--------- Transform lin to log Curve
function pos2vol(p) {
// Input 0 <= pos <= 1
// return a value value: -100 <= vol <= 0
p = (p<=0) ? 0.01 : (p<1) ? p : 1;
return (Math.log(p) * 50 / Math.LN10);
};
//--------- Transform log to lin Curve
function vol2pos(v){
// Input -100 <= vol <= 0
// return a value value: 0 <= pos <= 1
v = (v<=-100) ? -100 : (v<0) ? v : 0;
return (Math.pow(Math.E,(v * Math.LN10 / 50)))
}
//--------- Paint Volumebar
function on_paint(gr){
gr.SetTextRenderingHint(5);
ww = window.Width;
wh = window.Height;
volume = fb.Volume;
pos = wh * (1 - vol2pos(volume));
txt_Vol = (Math.ceil(volume));
gr.DrawImage( BgImg, 0, 0, ww, wh, 0, 0, BgImg.Width, BgImg.Height);
gr.FillSolidRect( 0,        0, ww, pos, RGBA(016,016,024,160));
gr.FillSolidRect( 0, pos-1, ww,     3, RGBA(255,000,255,192));
gr.DrawString( txt_Vol, StrFo_Vol, StrCo_Vol, 0, 0, ww, wh-12, StrFmt_Vol);
gr.DrawString(  txt_dB,  StrFo_dB, StrCo_dB, 0, 0, ww, wh-02, StrFmt_Vol);
}
//----------------------------------------------------------------------------
//------ Mouse
var g_drag = 0;
function on_mouse_lbtn_down(x,y){
g_drag = 1;
}
function on_mouse_lbtn_up(x,y){
on_mouse_move(x,y);
g_drag = 0;
}
function on_mouse_move(x,y){
if(g_drag){
var v = 1 - (y / wh);
v = (v<0) ? 0 : (v<1) ? v : 1;
v = pos2vol(v)
if(fb.Volume != v)
fb.Volume = v;
}
}
function on_mouse_wheel(delta){
if(delta>0)
fb.VolumeUp();
else
fb.VolumeDown();
}
//----------------------------------------------------------------------------
//------ Volume
function on_volume_change(val){
window.Repaint();
}
//EOF


In der Mitte, und mit abstand den meisten Platz einnehmend, ist nun die "Info & Seek Bar" die eine Menge Zusatzfunktionen bereithält und um die es mir hier in diesem "Faden" geht.


Als erstes muss ich voranschicken, das ich einige selbstdefinierte TAGS in meiner Sammlung nutze die sich in den letzten Jahren als NÖTIG oder ANGENEM erwiesen haben. Der älteste dieser TAG's  ist %INTRO%. Da ich über das Nutzen von Karaoke-Files zu f2k gekommen bin suchte ich nach einem Weg bei einigen Playbacks mit schwierigem Anfang einen Optischen Cue zu generieren wo der Gesang anfängt. Auch sind hier bei uns im Funkhaus alle Musikdateien mit einer Intro-Information versehen um dem Moderator den sogenannten Ramptalk zu erleichtern.

Auf diesem Weg würde ich nun auch gleich für die aufnahmen des %INTRO% TAGs als Standard-TAG plädieren.

Die weiteren TAGs die hier noch zum Einsatz kommen sind:

%PRETITLE%, %PRENUMBER%, %SUBTITLES% und %SUBTIMES%

Und die Standard-TAGs

%ARTIST%, %PERFORMER%, %ALBUM ARTIST% und %FEATURING%

Sowie

%TITLE% und %TITLEVERSION%.

Die beiden TAGs %PRETITLE% und %PRENUMBER% nutze ich wenn ein Musikalisches Werk über mehrere Tracknummern verteilt ist, Beispiel:

"The Fall Of The House Of Usher" von "The Alan Parsons Project" auf der CD "Tales Of Mystery And Imagination Edgar Allan Poe" Track 6 bis 10

%PRETITLE% bei den 5 Tracks = The Fall Of The House Of Usher
%TRACKNUMBER% = 6 / %PRENUMBER% = 1 / %TITLE% = Prelude
%TRACKNUMBER% = 7 / %PRENUMBER% = 2 / %TITLE% = Arrival
%TRACKNUMBER% = 8 / %PRENUMBER% = 3 / %TITLE% = Intermezzo
%TRACKNUMBER% = 9 / %PRENUMBER% = 4 / %TITLE% = Pavane
%TRACKNUMBER% = 10 / %PRENUMBER% = 5 / %TITLE% = Fall

Wohingegen die TAGs %SUBTITLES% und %SUBTIMES% dort Verwendung finden, wo z.B. in einem einzigen Audiofile mehrere Tracks vorhanden sind (Imagefils oder auch bei Medleys) oder ein größeres Musikalische Werk zwar Unterwerke aufweist, diese aber nicht einzelnen Tracks zugeordnet sind. Beispiel:

"Beatles Medley" von "Stars On 45"

%SUBTITLES% = Stars On 45; Venus; Sugar Sugar; No Reply; I'll Be Back; Drive My Car; A Hard Days Night; Do You Want To Know A Secret; We Can Work It Out; I Should Have Known Better; Nowhere Man; You're Going To Lose That Girl

%SUBTIMES% = 43; 51; 91; 107; 133; 164; 192; 208; 227; 235; 250

Da der erste Titel ja bei 0:00 Anfängt gibt es natürlich eine Subtime weniger wie es Subtitles gibt, und, das hätte ich beinahe noch vergessen, sowohl %INTRO% als auch %SUBTIMES% werden in Sekunden angegeben (macht das Rechnen und Formatieren einfacher).

Auf dem Screnshot oben sieht man nun, neben Artist- und Titel-Informationen, einen dunkelgrünen, hellgrünen und gelben Fortschrittsbalken. Der dunkelgrüne Balken steht für die Visualisierung des Intros und der hellgrüne für die Tracklänge. Der kleine gelbe Balken symbolisiert die Länge des entsprechenden Subtitles. Sowohl der gelbe als auch der hellgrüne Balken können durch "anfassen" mit der Maus bewegt werden und die Musik spielt dort weiter wo die Maus "losgelassen" wird.

-

Hier zeigt der von links wieder kleiner werdende Balken die Outro Zeit an. Diese ist willkürlich von mir auf 15 Sec bei Titeln länger 15 Sec gesetzt worden. Bei Titeln kürzer 15 beträgt die Outro Zeit die Hälfte des Titels.

-

Hier sehen wir das beim Titel "A Change Of Seasons" ein weitere Subtitle abgespielt wird. Die Zeitanzeige am unteren Rand bezieht sich immer auf den Subtitle. Sollten zwar Subtitles jedoch keine Subtimes "getagt" sein, so giebt es natürlich keinen gelben Balken und keine Zeitanzeige, woher auch. Des weiteren werden dann auch nicht die Namen der Subtitles  angezeigt, sondern nur die Anzahl der Takes.

-

Ein weiterer Subtitel aber die beiden roten Balken Signalisieren, das der Player auf PAUSE ist.

-

Hier sieht man nun, das der komplette Track bald zu Ende ist, auch auf Trackebene ist die gleiche Outrozeitberechnung wie bei den Subtitles integriert.

-

Hier jetzt ein Normaler Titel ohne Subtitles.

-

Und zum Schluss noch die Anzeige von %PRETITLE% und %PRENUMBER%.

Auf dem ersten Bild oben sieht man rechts unten neben den Laufwerksfunktionen noch die Bedieneinheit SUBTRACKS. Wenn keine Subtracks vorhanden sind ist nur der mittlere Button zu sehen mit dem Hinweistext "No Subtracks". Beim Vorhandensein von Tubtimes-Informationen kommen hier je nach Möglichkeit ein Play Next bzw, Play Previous Button zum Vorschein und der mittlere Butten zeigt an der wievielte Track von wie vielen gerade gespielt wird. Auch kann man hier eine Liste aufrufen mit den Titeln und Zeiten der einzelnen Tracks um dann einen direkt anzuspringen zu können.

Vielleicht kann ja der ein oder andere damit was anfangen, oder aber entdeckt noch einen Fehler, denn dies waren meine ersten Gehversuche in JScript, der Code ist im nächsten Beitrag, da dieser sonst zu lang ist.

Viel spass wünscht TomPro

Fehlerhafte Links entfernt - tedgo

TomPro

#1
[CUI]

Hier nun der Code:


//----------------------------------------------------------------------------
//--- 1stStrike Info & Seek Bar (by TomPro)
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//------ Global
//--------- Window
var ww = window.Width;
var wh = window.Height;

//--------- Set Color
function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r,g,b,a){ return ((a<<24)|(r<<16)|(g<<8)|(b)); }

//--------- Format Time String
function TimeFmt(t){
var zpad = function(n){
var str = n.toString();
return (str.length<2) ? "0"+str : str;
}
var h = Math.floor(t/3600); t-=h*3600;
var m = Math.floor(t/60); t-=m*60;
var s = Math.floor(t);
if(h>0) return h.toString()+":"+zpad(m)+":"+zpad(s);
return m.toString()+":"+zpad(s);
}

//----------------------------------------------------------------------------
//------ Text Options

//--------- Font
// format : x = gdi.Font("FontName", ptSize, FStyle.Style);
var FStyle = { Normal: 0, Bold: 1, Italic: 2, Underline: 4, Strikeout: 8 }

//--------- String Format
//------------ Align
var HAlign = { Left: 0, Center: 1, Right: 2 }
var VAlign = { Top: 0, Middle: 1, Bottom: 2 }

//------------ Trim
var Trim = { No: 0, Chara: 1, Word: 2, ElipsChara: 3, ElipsWord: 4, ElipsPath: 5 }

//------------ Flag
var Flag = {
Rtl: 0x0001,
Vert: 0x0002,
Nofit : 0x0004,
Dispctrl: 0x0020,
Nofallback: 0x0400,
Trailspace: 0x0800,
Nowrap: 0x1000,
Linelimit: 0x2000,
Noclip: 0x4000
}

//------------ Set String Format
function StrFmt(alignH,alignV,trim,flag){ return ((alignH<<28)|(alignV<<24)|(trim<<20)|flag); }

//----------------------------------------------------------------------------
//------ Seekbar
//--------- Strings
//------------ Font
var g_font_Artist = gdi.Font("Zurich Ex BT", 12, FStyle.Bold);
var g_font_Title = gdi.Font("Arial", 24, FStyle.Bold);
var g_font_Time = gdi.Font("Arial", 10, FStyle.Bold);

//------------ Colors
var c_Artist = RGB(255,255,255);
var c_Title = RGB(255,128,128);
var c_Time = RGB(255,255,096);

//------------ Formats
var StrFmt_Artist = StrFmt(HAlign.Center, VAlign.Top, Trim.No, Flag.Nowrap);
var StrFmt_Title = StrFmt(HAlign.Center, VAlign.Middle, Trim.No, Flag.Nowrap);
var StrFmt_Time = StrFmt(HAlign.Center, VAlign.Bottom, Trim.No, Flag.Nowrap);

//------------ Get Strings
var txt_Artist = fb.TitleFormat("$if3($meta_sep(artist,', ',' & '),$meta_sep(performer,', ',' & '),$meta_sep(album artist,', ',' & '),'No ARTIST')$if(%featuring%,' feat. '%featuring%,)");
var txt_Title;
var txt_TitleA = fb.TitleFormat("$if(%pretitle%,%pretitle%': '$char(10),)");
var txt_TitleB = fb.TitleFormat("$if(%prenumber%,%prenumber%' - ',)$if2(%title%,'File : '%filename%)$if(%titleversion%,' ('%titleversion%') ',)");
var txt_TitleC;

//--------- Times
//var g_pb_length = fb.TitleFormat("%length%");
//var g_pb_length_sec = fb.TitleFormat("%length_seconds%");
var g_pb_length_intro = fb.TitleFormat("$ifgreater(%intro%,0,%intro%,0)");
var g_pb_length_outro = fb.TitleFormat("$ifgreater(%length_seconds%,15,15,$div(%length_seconds%,2))");

//var g_pb_time = fb.TitleFormat("%playback_time%");
//var g_pb_time_sec = fb.TitleFormat("%playback_time_seconds%");
//var g_pb_time_rem = fb.TitleFormat("%playback_time_remaining%");
//var g_pb_time_rem_sec = fb.TitleFormat("%playback_time_remaining_seconds%");
var g_pb_time_intro = fb.TitleFormat("$ifgreater($sub($ifgreater(%intro%,0,%intro%,0),%playback_time_seconds%),0,$sub($ifgreater(%intro%,0,%intro%,0),%playback_time_seconds%),0)");
var g_pb_time_outro = fb.TitleFormat("$ifgreater($sub(%playback_time_remaining_seconds%,$ifgreater(%length_seconds%,15,15,$div(%length_seconds%,2))),0,$ifgreater(%length_seconds%,15,15,$div(%length_seconds%,2)),%playback_time_remaining_seconds%)");

//------------ Get Times
var pos, intro, outro, length, now;
var txt_Time,txt_TimeI,txt_TimeO;

var g_drag = 0;
var g_drag_seek = 0;

function GetTimes(){
ww = window.Width;
wh = window.Height;
length = fb.PlaybackLength;
now = fb.PlaybackTime;

pos = 0; intro = 0; outro = 0;
txt_Time = ""; txt_TimeI = ""; txt_TimeO = "";

if(length > 0) {
if(g_drag) {
if(g_drag == 1) {
pos = ww * g_drag_seek;
txt_Time = "<   <<   <<<        " + TimeFmt(g_drag_seek * length);
txt_Time += "  |  " + TimeFmt(length) + "  |  ";
txt_Time += TimeFmt(length - (g_drag_seek * length)) + "        >>>   >>   >";
} else {
SubPos = ww * g_drag_seek;
}

} else {
pos = ww * (now / length);
outro = ww * ( 1 - (g_pb_time_outro.eval() / g_pb_length_outro.eval()));
if(g_pb_length_intro.eval()==0) {
intro = ww * 1;
} else {
intro = ww * ( 1 - (g_pb_time_intro.eval() / g_pb_length_intro.eval()));
}
}
}
}

//--------- Colors
//------------ Stop
var c_stop_BA = RGBA(016,016,024,255); var c_stop_BB = RGBA(016,016,024,255);
var c_stop_TA = RGBA(016,016,024,100); var c_stop_TB = RGBA(016,016,024,000);

//------------ Sub
var c_Sub_BA = RGBA(255,255,000,255); var c_Sub_BB = RGBA(016,016,000,128);
var c_Sub_TA = RGBA(016,016,000,192); var c_Sub_TB = RGBA(096,096,000,032);

//------------ Play
var c_play_BA = RGBA(000,255,000,255); var c_play_BB = RGBA(000,032,000,255);
var c_play_TA = RGBA(000,032,000,192); var c_play_TB = RGBA(000,255,000,000);
var c_iplay_BA = RGBA(000,160,000,255); var c_iplay_BB = RGBA(000,032,000,255);
var c_iplay_TA = RGBA(000,032,000,192); var c_iplay_TB = RGBA(000,255,000,000);

//------------ Pause
var c_pause_BA = RGBA(255,000,000,255); var c_pause_BB =RGBA(032,000,000,255);
var c_pause_TA = RGBA(016,000,000,192); var c_pause_TB = RGBA(255,000,000,000);
var c_ipause_BA = RGBA(160,000,000,255); var c_ipause_BB = RGBA(032,000,000,255);
var c_ipause_TA = RGBA(032,000,000,192); var c_ipause_TB = RGBA(255,000,000,000);

//------------ Get Colors
var c_isplay_BA, c_isplay_BB, c_isplay_TA, c_isplay_TB;
var c_iisplay_BA, c_iisplay_BB, c_iisplay_TA, c_iisplay_TB;

function GetColors(){
if(fb.IsPaused){
c_isplay_BA = c_pause_BA; c_isplay_BB = c_pause_BB;
c_isplay_TA = c_pause_TA; c_isplay_TB = c_pause_TB;
c_iisplay_BA = c_ipause_BA; c_iisplay_BB = c_ipause_BB;
c_iisplay_TA = c_ipause_TA; c_iisplay_TB = c_ipause_TB;
}else{
c_isplay_BA = c_play_BA; c_isplay_BB = c_play_BB;
c_isplay_TA = c_play_TA; c_isplay_TB = c_play_TB;
c_iisplay_BA = c_iplay_BA; c_iisplay_BB = c_iplay_BB;
c_iisplay_TA = c_iplay_TA; c_iisplay_TB = c_iplay_TB;
}
}

//----------------------------------------------------------------------------
//------ Sub Titles & Seekbar
var SubTakes = fb.TitleFormat("$meta_num(subtitles)");
var SubTitlesArray = new Array (SubTakes.eval());
var SubTimesNum = fb.TitleFormat("$meta_num(subtimes)");
var SubTimesArray = new Array (SubTimesNum.eval() + 1);

var SubTitle = "";
var SubTake = 0;
var SubStart = 0;
var SubEnd = 0;
var SubLength = 0;
var SubTime = "";
var SubPlayed = 0;
var SubRemain = 0;
var SubNow = 0;
var SubPos = 0;
var SubOutro = 0;
var SubPosOutro = 0;

function GetSubTitles() {
var SubTitles = ";###; " + fb.TitleFormat("$meta_sep(subtitles,';###; ')").eval();
SubTitlesArray = SubTitles.split(";###; ");
if(SubTimesNum.eval() > 0) {
GetSubTimes() ;
} else {
txt_TitleC = "\n[ " + SubTakes.eval() + " Takes ]";
}
}

function GetSubTimes() {
var SubTimes = ";###; 0;###; " + fb.TitleFormat("$meta_sep(subtimes,';###; ')").eval() + ";###; " + length;
SubTimesArray = SubTimes.split(";###; ");
for (var i = 1; i <= SubTakes.eval(); i++) {
if(Number(now) >= Number(SubTimesArray[i])) {
SubTake = i;
}
}
SubTitle = SubTitlesArray[SubTake];
SubStart = Number(SubTimesArray[SubTake]);
SubEnd = Number(SubTimesArray[SubTake + 1]);
SubLength = SubEnd - SubStart;
SubTime = TimeFmt(SubLength);
SubOutro = (SubLength > 15) ? 15 : SubLength / 2;
SubRemain = TimeFmt(Number(SubEnd) - Math.floor(now));
SubPosOutro = ((Number(SubEnd) - Math.floor(now)) > SubOutro) ? 0 : ww * (1 - ((Number(SubEnd) - Math.floor(now)) / (SubOutro)));
SubNow = Math.floor(now) - SubStart;
SubPlayed = TimeFmt(SubNow);
if (!g_drag) {
SubPos = (ww * ((SubNow) / SubLength)) - SubPosOutro;
txt_Time = SubPlayed + "  |  " + SubTime + "  |  " + SubRemain;
} else {
SubPosOutro = 0;
txt_Time = "<   <<   <<<        " + TimeFmt(g_drag_seek * SubLength);
txt_Time += "  |  " + SubTime + "  |  ";
txt_Time += TimeFmt(SubLength - (g_drag_seek * SubLength)) + "        >>>   >>   >";
}
txt_TitleC = "\n[ " + SubTitle + " ]";
}

//----------------------------------------------------------------------------
//------ Painting
function on_paint(gr){
GetTimes();
GetColors();

gr.FillGradRect( 0, 0,    ww,    wh, 90,   c_stop_BA,   c_stop_BB); // Bottom - Stop - Right Side
gr.FillGradRect( 0, 0,    ww, wh/2, 90,   c_stop_TA,   c_stop_TB); // Top - Stop - Right Side Top
gr.FillGradRect( 0, 0,  intro,    wh, 90, c_iisplay_BA, c_iisplay_BB); // Bottom - Intro - Right Side Bottom
gr.FillGradRect( 0, 0,  intro, wh/2, 90, c_iisplay_TA, c_iisplay_TB); // Top - Intro - Right Side Top
gr.FillGradRect( 0, 0,    pos,    wh, 90,  c_isplay_BA,  c_isplay_BB); // Bottom - Timebar
gr.FillGradRect( 0, 0,    pos, wh/2, 90,  c_isplay_TA,  c_isplay_TB); // Top - Timebar

if(SubTakes.eval() > 0) {
GetSubTitles();
if(SubTimesNum.eval() > 0) {
gr.FillGradRect( SubPosOutro, wh-18,  SubPos, 20, 90,  c_Sub_BA,  c_Sub_BB); // Bottom - Sub Timebar
gr.FillGradRect( SubPosOutro, wh-19,  SubPos, 13, 90,  c_Sub_TA,  c_Sub_TB); // Top - Sub Timebar
}
} else {
txt_TitleC = "";
}

gr.FillGradRect( 0, 0, outro,    wh, 90,    c_stop_BA,    c_stop_BB); // Bottom - Outro - Left Side Bottom
gr.FillGradRect( 0, 0, outro, wh/2, 90,    c_stop_TA,    c_stop_TB); // Top - Outro - Left Side

txt_Title = txt_TitleA.eval() + txt_TitleB.eval() + txt_TitleC;

gr.DrawString( txt_Artist.eval(), g_font_Artist, c_Artist, 0, 0, ww, wh, StrFmt_Artist);
gr.DrawString(             txt_Title,  g_font_Title,   c_Title, 0, 0, ww, wh, StrFmt_Title);
gr.DrawString(            txt_Time,  g_font_Time,  c_Time, 0, 0, ww, wh, StrFmt_Time);

}
//----------------------------------------------------------------------------
//------ Window
function on_size(){
window.Repaint();
}

//----------------------------------------------------------------------------
//------ Mouse
function on_mouse_lbtn_down(x,y) {
g_drag = ((y >= (wh - 20)) && (SubTakes.eval() > 0)) ? 2 : 1;
}
function on_mouse_lbtn_up(x,y) {
if(g_drag) {
g_drag_seek = x / ww;
g_drag_seek = (g_drag_seek<0) ? 0 : (g_drag_seek<1) ? g_drag_seek : 1;
if(g_drag == 1) {
fb.PlaybackTime = fb.PlaybackLength * g_drag_seek;
} else {
fb.PlaybackTime = SubStart + (SubLength * g_drag_seek);
}
g_drag = 0;
}
}
function on_mouse_move(x,y){
if(g_drag) {
g_drag_seek = x / ww;
g_drag_seek = (g_drag_seek<0) ? 0 : (g_drag_seek<1) ? g_drag_seek : 1;
window.Repaint();
}
}
function on_mouse_wheel(delta){
if(fb.IsPlaying){
if(fb.IsPaused){
if(delta>0)
fb.PlaybackTime += 0.1;
else
fb.PlaybackTime -= 0.1;
}else{
if(delta>0)
fb.PlaybackTime += 1;
else
fb.PlaybackTime -= 1;
}
}
}

//----------------------------------------------------------------------------
//------ Playback
function on_playback_new_track(metadb) {
window.Repaint();
}
function on_playback_stop(reason) {
window.Repaint();
}
function on_playback_edited() {
window.Repaint();
}
function on_playback_starting(cmd, paused){
window.Repaint();
}
function on_playback_new_track(info){
window.Repaint();
}
function on_playback_stop(){
window.Repaint();
}
function on_playback_seek(time){
window.Repaint();
}
function on_playback_pause(state){
window.Repaint();
}
function on_playback_edited(){
window.Repaint();
}
function on_playback_time(time){
window.Repaint();
}

//  EOF



TomPro

#2
[CUI]

So, nachdem ich nun auch noch eine Idee für die zweite (rechte) Ratinganzeige hatte kommen hier die beiden Codes. Zunächst die linke Anzeige für den normalen Ratig-TAG:

//----------------------------------------------------------------------------
//--- 1stStrike Rating (by TomPro) v1.0
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//------ Global
//--------- Window
var ww = window.Width;
var wh = window.Height;

//--------- Set Color
function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r,g,b,a){ return ((a<<24)|(r<<16)|(g<<8)|(b)); }

//--------- Get Positions
var rh, rw, rr, wwA, wwB;
var RaH = new Array(6);

function get_positions(){
wh = window.Height; // Height of the Window
ww = window.Width; // Width of the Window

rh = Math.round(wh / 12); // Height of each Rating Sign
rw = Math.round(ww / 2) + 1; // Width of each Rating Sign
rr = Math.round(rh / 2) - 1; // Rectangle Round of each Rating Sign
rr = (rr < (rw / 2)) ? rr : Math.round(rw / 2) - 1; // Check that rr don't become too great

wwA = Math.round(ww / 2) - Math.round(rw / 3); // Left Position (x) of each Rating Sign

RaH[3] = Math.round(wh / 2) - Math.round(rh / 2); // Top Position (y) of the 3rd Rating Sign
RaH[1] = RaH[3] + Math.round(3.50 * rh); // Top Position (y) of the 1st Rating Sign
RaH[2] = RaH[3] + Math.round(1.75 * rh); // Top Position (y) of the 2nd Rating Sign
RaH[4] = RaH[3] -  Math.round(1.75 * rh); // Top Position (y) of the 4th Rating Sign
RaH[5] = RaH[3] -  Math.round(3.50 * rh); // Top Position (y) of the 5th Rating Sign
}

//----------------------------------------------------------------------------
//------ Rating
var Rating = fb.TitleFormat("$meta(rating)"); // Get Rating from Rating-Tag (Manuel)

//--------- Rating Color
var RaCoA = RGB(128,128,192); // Color of Normal Border of each Rating Sign
var RaCoB = RGB(192,255,192); // Color of Hover-EFX by mouse Border of one Rating Sign (for later use to edit the Tag-Field)

var RaCo = new Array(6); // Colors of each Rating Sign (from dark (1) to light (5))
for (var i = 1; i < RaCo.length; i++) { RaCo[i]=RGB(160,i * 16 + 48,160) };

//----------------------------------------------------------------------------
//------ Painting
function on_paint(gr){
get_positions()

r = Rating.eval()
r = (r<0) ? 0 : (r<6) ? r : 0;
r = Math.round(r) + 1;

var hr = (wh<70) ? wh / 2 - 1 : 35;

// Backround
gr.FillSolidRect(    0, 0, ww, wh,            RGB(016,016,024));
gr.FillRoundRect( 0, 0, ww, wh, 15, hr, RGB(000,000,096));
gr.FillSolidRect(  17, 0, ww, wh,            RGB(000,000,096));
gr.FillGradRect(    0, 0, ww, wh, 0,        RGBA(016,016,024,096), RGBA(128,128,160,096));

// Rating
for (var i = 1; i < RaCo.length; i++) {
if (r>i) {
gr.FillRoundRect(wwA, RaH[i], rw, rh, rr, rr,     RaCo[i]);
}
gr.DrawRoundRect(wwA, RaH[i], rw, rh, rr, rr, 1, RaCoA);
}
}

//----------------------------------------------------------------------------
//------ Window
function on_size() {
get_positions();
window.Repaint();
}

//----------------------------------------------------------------------------
//------ Playback
function on_playback_new_track(metadb) {
window.Repaint();
}
function on_playback_stop(reason) {
window.Repaint();
}
function on_playback_edited() {
window.Repaint();
}

//EOF


Und dann die rechte Anzeige:

//----------------------------------------------------------------------------
//--- 1stStrike Rating (Playcount / Raiting) (by TomPro) v1.0
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//------ Global
//--------- Variable
var INI_File = fb.FoobarPath + "1stStrike\\1stStrike.ini" // Path and Name of the INI Inifile

//--------- Window
var ww = window.Width; // Height of the Window
var wh = window.Height; // Width of the Window

//--------- Set Color
function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r,g,b,a){ return ((a<<24)|(r<<16)|(g<<8)|(b)); }

//--------- Get Positions
var rh, rw, rr, wwA;
var RaH = new Array(6);

function get_positions(){
wh = window.Height;
ww = window.Width;

rh = Math.round(wh / 12); // Height of each Rating Sign
rw = Math.round(ww / 2) + 1; // Width of each Rating Sign
rr = Math.round(rh / 2) - 1; // Rectangle Round of each Rating Sign
rr = (rr < (rw / 2)) ? rr : Math.round(rw / 2) - 1; // Check that rr don't become too great

wwA = Math.round(ww / 2) - 2 *Math.round(rw / 3); // Left Position (x) of each Rating Sign

RaH[3] = Math.round(wh / 2) - Math.round(rh / 2); // Top Position (y) of the 3rd Rating Sign
RaH[1] = RaH[3] + Math.round(3.50 * rh); // Top Position (y) of the 1st Rating Sign
RaH[2] = RaH[3] + Math.round(1.75 * rh); // Top Position (y) of the 2nd Rating Sign
RaH[4] = RaH[3] -  Math.round(1.75 * rh); // Top Position (y) of the 4th Rating Sign
RaH[5] = RaH[3] -  Math.round(3.50 * rh); // Top Position (y) of the 5th Rating Sign
}

//----------------------------------------------------------------------------
//------ Rating
var StressR = Number(utils.ReadINI(INI_File, "Statistic", "StressR",1));
var StressC = Number(utils.ReadINI(INI_File, "Statistic", "StressC",1));
var RatingStress;
var Rating = fb.TitleFormat("$meta(rating)"); // Get Rating from Rating-Tag (Manuel)
var PlayCount = fb.TitleFormat("%play_count%"); // Get Rating from Play Count-Tag
var CountMax = Number(utils.ReadINI(INI_File, "Statistic", "Playcount"));
var CountRatio = 250 / CountMax;

//--------- Rating Color
var RaCoA = RGB(128,128,192); // Color of Normal Border of each Rating Sign
var RaCoB = RGB(192,255,192); // Color of Hover-EFX by mouse Border of one Rating Sign (for later use to edit the Tag-Field)

var RaCo = new Array(6); // Colors of each Rating Sign (from dark (1) to light (5))
for (var i = 1; i < RaCo.length; i++) { RaCo[i]=RGB(160,i * 16 + 48,160) };

function get_rating(){
var RatingHalf = ((Rating.eval()<0) ? 0 : (Rating.eval()<6) ? Rating.eval() : 0)  * 50 * StressR;
if (PlayCount.eval() <= CountMax) {
var CountingHalf = PlayCount.eval() * CountRatio * StressC;
} else {
CountMax = PlayCount.eval();
CountRatio = 250 / CountMax
var CountingHalf = 250 * StressC;
utils.WriteINI(INI_File, "Statistic", "Playcount", CountMax);
utils.WriteINI(INI_File, "Statistic", "Title", fb.TitleFormat("$meta(Title)").eval());
utils.WriteINI(INI_File, "Statistic", "Artist", fb.TitleFormat("$meta(Artist)").eval());
utils.WriteINI(INI_File, "Statistic", "Album", fb.TitleFormat("$meta(Album)").eval());
utils.WriteINI(INI_File, "Statistic", "Rating", fb.TitleFormat("$meta(Rating)").eval());
}
RatingStress = (RatingHalf + CountingHalf) / ((StressR + StressC) * 50);
}

//----------------------------------------------------------------------------
//------ Setup Menu
var MFlag = {
Enabled: 0x00000000,
String: 0x00000000,
Unchecked: 0x00000000,
Grayed: 0x00000001,
Disabled: 0x00000002,
Bitmap: 0x00000004,
Checked: 0x00000008,
Popup: 0x00000010,
MenuBarBreak: 0x00000020,
MenuBreak: 0x00000040,
OwnerDraw: 0x00000100,
Separator: 0x00000800,
RightJustify: 0x00004000
};

function ShowSetup(x,y) {
get_rating()
var _Menu = window.CreatePopupMenu();
var ret;

_Menu.AppendMenuItem(MFlag.Disabled, 0, "Stress Playcount  ( " + PlayCount.eval() + " )");
for(var i=1; i<=10; i++) {
_Menu.AppendMenuItem(MFlag.String, i, i);
}
_Menu.AppendMenuSeparator();
_Menu.AppendMenuItem(MFlag.Disabled, 19, "Stress Rating  ( " + Rating.eval() + " )");
for(var i=0; i<=10; i++) {
_Menu.AppendMenuItem(MFlag.String, 20 + i, i);
}
_Menu.AppendMenuSeparator();
_Menu.AppendMenuItem(MFlag.Disabled, 40, "Highest Playcount  ( " + utils.ReadINI(INI_File, "Statistic", "Playcount") + " )");
_Menu.AppendMenuItem(MFlag.Grayed, 42, "Title = " + utils.ReadINI(INI_File, "Statistic", "Title"));
_Menu.AppendMenuItem(MFlag.Grayed, 43, "Artist = " + utils.ReadINI(INI_File, "Statistic", "Artist"));
_Menu.AppendMenuItem(MFlag.Grayed, 44, "Album = " + utils.ReadINI(INI_File, "Statistic", "Album"));
_Menu.AppendMenuItem(MFlag.Grayed, 45, "Rating = " + utils.ReadINI(INI_File, "Statistic", "Rating"));

_Menu.CheckMenuRadioItem(01, 10, StressC);
_Menu.CheckMenuRadioItem(20, 30, StressR + 20);

ret = _Menu.TrackPopupMenu(x,y);
if (ret == 0) return;
if (ret >= 01 && ret <= 10) {
StressC = ret;
utils.WriteINI(INI_File, "Statistic", "StressC", StressC);
}
if (ret >= 20 && ret <= 30) {
StressR = ret - 20;
utils.WriteINI(INI_File, "Statistic", "StressR", StressR);
}
}

//----------------------------------------------------------------------------
//------ Painting
function on_paint(gr){
get_rating()
get_positions()

r = RatingStress;
r = (r<0) ? 0 : (r<6) ? r : 0;
r = Math.round(r) + 1;

var hr = (wh<70) ? wh / 2 - 1 : 35;

// Backround
gr.FillSolidRect(    0, 0, ww, wh,            RGB(016,016,024));
gr.FillRoundRect( 0, 0, ww, wh, 15, hr, RGB(000,000,096));
gr.FillSolidRect(    0, 0,  17, wh,            RGB(000,000,096));
gr.FillGradRect(    0, 0, ww, wh, 180,    RGBA(016,016,024,096), RGBA(128,128,160,096));

// Rating
for (var i = 1; i < RaCo.length; i++) {
if (r>i) {
gr.FillRoundRect(wwA, RaH[i], rw, rh, rr, rr,     RaCo[i]);
}
gr.DrawRoundRect(wwA, RaH[i], rw, rh, rr, rr, 1, RaCoA);
}
}

//----------------------------------------------------------------------------
//------ Window
function on_size() {
get_positions()
window.Repaint();
}

//----------------------------------------------------------------------------
//------ Playback
function on_playback_new_track(metadb) {
window.Repaint();
}
function on_playback_stop(reason) {
window.Repaint();
}
function on_playback_edited() {
window.Repaint();
}

//--------- Mouse
// mask: see Flags.txt for more details
function on_mouse_lbtn_down(x,y,mask) {
ShowSetup(x,y);
window.Repaint();
}

//EOF


Bei der rechten Rating Anzeige handelt es sich um eine Kombination aus Rating und Playcount. Beim abspielen der Tracks wird dabei der aktuelle Playcount Wert des laufenen Tracks ermittelt und mit dem bis daher höchsten Playcount Wert verglichen. Sollte der aktuelle Playcout Wert höher sein, so wird dieser automatisch der nächste Masstab an dem sich die folgenden zu richten haben. Der höchste ermittelte Wert wird in eine INI-Datei geschrieben, damit der Wert natürlich nicht verloren geht. Das Playcount-Rating setzt den höchsten Wert auf 5 Punkte und im Verhältniss die anderen Werte entsprechend.

Zusätzlich daduzu kann mit der linken Maustaste ein Menue aufgerufen werden, wo das Verhältnis von Playcout-Rating (1 - 10) zu Normalen Rating (0 - 10) gesetzt werden kann.

Gruß TomPro

PS: Die Idee mit der INI-Datei hat mich dazu wiederum angeregt ein Album-Rating mit hilfe einer eigenen Datenbank auf diese Art zu entwickeln, so jagt eine Idee die nächste, mal sehen ob ich das hinbekomme.

tedgo

Ist ja ganz nett, aber irgendwie verstehe ich den Sinn des "rechten" Scripts noch nicht...
Muss es mir mal genau durchlesen, was es denn nun tut :)

Aber mal eine Frage:
Sollte nicht eine INI-Datei geschrieben werden, wenn ich mit Klick "Stress Playcount" oder "Stress Rating" ändere?
Wo wird die hingeschrieben?
Oder muss ich die selbst anlegen?
Wie gesagt, hab mir das Script noch nicht durchgelesen, nur einfach mal schnell in eine Testconfig kopiert :)

TomPro

#4
[CUI]

Zitat von: tedgo in 20. Juni 2009, 09:39:43...
Aber mal eine Frage:
Sollte nicht eine INI-Datei geschrieben werden, wenn ich mit Klick "Stress Playcount" oder "Stress Rating" ändere?
Wo wird die hingeschrieben?...

Stand in Zeile 8 ganz als erste Anweisung ::)

var INI_File = fb.FoobarPath + "1stStrike\\1stStrike.ini" // Path and Name of the INI Inifile

und müsste sich eigentlich selber erzeugen.

Das Script generiert ein Rating in Abhängigkeit von Playcount (alleine wenn Rating Stress auf 0) und Rating, und die Art der Gewichtung z.B. 1 zu 1 oder 3 zu 2 kann ich selber bestimmen. Das ich die Gewichtung über die Stress Parameter einstellbar gemacht habe ist dem Umstand geschuldet, das ich diese f2k-Version und die entsprechenden Plug-Ins erst seit ein paar Wochen (4 - 5) nutze und ich deswegen noch keine hohen und umfassende Statistikwerte habe, und deshalb noch nicht übersehen kann ob ein alleiniges Playcount Rating interessant für mich sein könnte. Für die Karaoke-Shows, welche ich ab und an betreue, kann sich dadurch zumindest eine Art Hitparade der beliebtesten Karaokenummern ergeben. Ansonsten war es für mich eine Denksportaufgabe was so möglich sein könnte. Mein Augenmerk liegt ja mehr auf der Funktionsergänzung als auf der Optik, für die ich Dir übrigen bei deinem DarkOne ein Lob aussprechen möchte (hat mich ein wenig angespornt mich in das Intensive f2k programmieren zu stürzen).

Gruß TomPro



tedgo

Also die INI-Datei wird bei mir nicht erzeugt...
Muss ich doch mal ins Script schauen (sobald ich genug Zeit dazu habe, denn dein Script-Stil ist ein bisschen anders als meiner. Da muss ich mich erst reindenken :)).

Die Funktion des Scripts habe ich jetzt umrissen. War nur etwas von den beiden "Stress"-Werten und deren gegenseitiger Wirkungsweise irritiert.
Eine gar nicht so unelegante Art, ein "Auto-Rating" zu fabrizieren. Ich gehe ja auch da einen anderen (simpleren) Weg.

TomPro

Zitat von: TomPro in 19. Juni 2009, 22:39:24...
PS: Die Idee mit der INI-Datei hat mich dazu wiederum angeregt ein Album-Rating mit hilfe einer eigenen Datenbank auf diese Art zu entwickeln, so jagt eine Idee die nächste, mal sehen ob ich das hinbekomme.

Für die die es interessiert, die Mathematik für das Albumrating steht schon mal und die ersten versuche mit einer eigenen Datenbank mithilfe der INI-Funktion des WSH Panel Mod sind vielversprechend. Die Art wie ich das Albumrating ermittle ist Folgende:

Tracklänge mal TrackRating geteilt durch Spielzeit des Albums.

Gruß TomPro

tedgo

An einem Album-Rating-Script wäre ich auch interessiert (falls ich es denn hinbekomme, dass die INI-Datei erzeugt wird...).
Allerdings passt das jetzt nicht mehr so ganz zum Topic-Titel...
Vielleicht solltest du ihn umbenennen, z. B. "WSH Panel mod - Scriptbeispiele" oder so ähnlich. Denn eigentlich passt ja auch das Rating-Script schon nicht mehr zum Titel ;)

TomPro

Ob sich die INI selbst erstellt hat kann ich schon nicht mehr sagen, da ich auch andere Parameter dort Ausgelagert hatte, Quasi als Globel Variable Derivat auf die mehrere Insanzen des WSH Panel Mods drauf zugreifen können.

Und --- Du hast recht alles weitere in einem anderen (passenden) Thread.

Gruß TomPro

TomPro

Zitat von: tedgo in 21. Juni 2009, 00:07:49
An einem Album-Rating-Script wäre ich auch interessiert (falls ich es denn hinbekomme, dass die INI-Datei erzeugt wird...)....

Also, gerade nochmal probiert, eine Datei, ob INI, DAT, TXT oder sonst was, wird automatisch erzeugt, jedoch nicht ein Ordner der Angegeben ist wenn dieser noch nicht Vorhanden ist. Hier lag wohl die Schwierigkeit mit meinem Script, da du bestimmt keinen Unterordner im foobar-Verzeichnis mit dem namen 1stStrike hattest. Lege also den Ordner 1stStike an und es wird funktionieren, genauso, wie wenn du den Pfad im Script auf --- sagen wir mal --- DarkOne änderst.

Viel Spaß bei den neu erworbenen Erkenntnissen

Gruß TomPro

TomPro

#10
[CUI]

So, nach 2 durchgemachten Nächten hier der erste Versuch eines AlbumRatings, kombiniert mit einigen Albuminformationen und einer Covereinbindung:

Fehlerhafter Link entfernt - tedgo

und der Code dazu:

//----------------------------------------------------------------------------
//--- 1stStrike Album Art & Info (by TomPro) v 0.8
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//------ Global
//--------- Variable
var INI_File = fb.FoobarPath + "1stStrike\\1stStrike.ini" // Path and Name of the INI Inifile
var DAT_File = fb.FoobarPath + "1stStrike\\albuminfo.dat" // Path and Name of the INI Inifile
var NC_Cover = fb.FoobarPath + "1stStrike\\IMG\\NoCover.png" // Path and Name of a No Cover Image
var File_Path = fb.TitleFormat("$directory_path(%path%)") // Path  of a played File
var get_ini_data, g_img;

var AI = { NoCover: 0, Front: 1, Back: 2, Disc : 3, Icon: 4, Artist: 5, Embedded: 6 }
get_ini_data = utils.ReadINI(INI_File, "Album Art", "StandardArtId", AI.Embedded);
var ArtIdS = Number(get_ini_data); //  Kind of Cover Standard
var ArtId = ArtIdS; //  Kind of Cover
var ArtCheck = new Array(6); // Check IDs of existing Cover

var TMI = { NowPlaying: 1, FollowCurser: 2 };
var TrackMode = TMI.FollowCurser;
var TMT = new Array( "Now Playing", "Follow Curser" );
var TM_Item = new Array(2);

//--------- Window
var ww = window.Width; // Height of the Window
var wh = window.Height; // Width of the Window

//--------- Set Color
function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r,g,b,a){ return ((a<<24)|(r<<16)|(g<<8)|(b)); }

//--------- Format Time String
function TimeFmt(t){
var zpad = function(n){
var str = n.toString();
return (str.length<2) ? "0"+str : str;
}
var h = Math.floor(t/3600); t-=h*3600;
var m = Math.floor(t/60); t-=m*60;
var s = Math.floor(t);
if(h>0) return h.toString()+":"+zpad(m)+":"+zpad(s);
return m.toString()+":"+zpad(s);
}

//----------------------------------------------------------------------------
//------ Text Options
//--------- Font
// format : x = gdi.Font("FontName", ptSize, FStyle.Style);
var FStyle = { Normal: 0, Bold: 1, Italic: 2, Underline: 4, Strikeout: 8 }

//--------- String Format
//------------ Align
var HAlign = { Left: 0, Center: 1, Right: 2 }
var VAlign = { Top: 0, Middle: 1, Bottom: 2 }

//------------ Trim
var Trim = { No: 0, Chara: 1, Word: 2, ElipsChara: 3, ElipsWord: 4, ElipsPath: 5 }

//------------ Flag
var Flag = {
Rtl: 0x0001,
Vert: 0x0002,
Nofit : 0x0004,
Dispctrl: 0x0020,
Nofallback: 0x0400,
Trailspace: 0x0800,
Nowrap: 0x1000,
Linelimit: 0x2000,
Noclip: 0x4000
}

//------------ Set String Format
function StrFmt(alignH,alignV,trim,flag){ return ((alignH<<28)|(alignV<<24)|(trim<<20)|flag); }

//----------------------------------------------------------------------------
//------ Album Art and Info
//--------- Strings
//------------ Font
var font_Artist = gdi.Font("Zurich Ex BT", 13, FStyle.Normal);
var font_Album = gdi.Font("Tahoma", 13, FStyle.Bold);
var font_Date = gdi.Font("Tahoma", 9, FStyle.Normal);
var font_Rating = gdi.Font("Arial",10, FStyle.Bold);
var font_Number = gdi.Font("Arial", 9, FStyle.Bold);
var font_Title = gdi.Font("Zurich Ex BT", 10, FStyle.Normal);
var font_Time = gdi.Font("Arial", 10, FStyle.Bold);

//------------ Colors
var c_Artist = RGB(128,128,000);
var c_Album = RGB(255,255,000);
var c_Date = RGB(192,192,000);
var c_Rating = RGB(255,192,192);
var c_Number = RGB(128,192,128);
var c_NumberPlay = RGB(255,128,128);
var c_Title = RGB(128,255,128);
var c_Time = RGB(255,255,096);

//------------ Formats
var StrFmt_Artist = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Album = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Date = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Rating = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Number = StrFmt(HAlign.Left, VAlign.Middle, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Title = StrFmt(HAlign.Left, VAlign.Middle, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Time = StrFmt(HAlign.Right, VAlign.Middle, Trim.No, Flag.Nowrap);

//--------- Album Art Ratio
var wr, iw, ih, iws, ihs, irs;

function GetRatio(image) {
ww = window.Width;
wh = window.Height;
wr = ww/(wh); // Ratio of the Windows minus 15 px Head
iws = image.Width; // Source-Width of the Selected Cover
ihs = image.Height; // Source-Height of the Selected Cover
irs = iws/ihs; // Ratio of the Selected Cover

if (wr > irs) {
iw = Math.round(wh * irs); // Width of the Selected Cover
ih = wh; // Height of the Selected Cover
} else {
iw = ww; // Width of the Selected Cover
ih = Math.round(ww / irs); // Height of the Selected Cover
}
}

//--------- Album Art
ActualItem()

function ActualItem() {
TM_Item[TMI.NowPlaying] = fb.GetNowPlaying();
TM_Item[TMI.FollowCurser] = fb.GetFocusItem();
}

function CheckImage(Item) {
var c_img = null;
ActualItem();
if (! TM_Item[Item] ){
for (var i = 6; i >= 0; i--) { ArtCheck[i]  =  0; }
} else {
ArtCheck[0] = 0;
for (var i = 5; i >= 1; i--) {
c_img = utils.GetAlbumArt(TM_Item[Item].RawPath, i-1);
ArtCheck[i] = (c_img) ? 1 : 0;
ArtCheck[0] = (c_img) ? i : ArtCheck[0];
}
c_img = utils.GetAlbumArtEmbedded(TM_Item[Item].RawPath, 0);
ArtCheck[6] = (c_img) ? 1 : 0;
ArtCheck[0] = (c_img) ? 6 : ArtCheck[0];
}
}

function SelectImage() {
TrackMode = (fb.isplaying) ? TMI.NowPlaying: TMI.FollowCurser;
CheckImage(TrackMode);
var SelectId = (ArtCheck[ArtId] == 1) ? ArtId : ArtCheck[0];
switch(SelectId) {
case AI.NoCover:
g_img = gdi.Image(NC_Cover);
break;
case AI.Front:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 0);
break;
case AI.Back:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 1);
break;
case AI.Disc:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 2);
break;
case AI.Icon:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 3);
break;
case AI.Artist:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 4);
break;
case AI.Embedded:
g_img = utils.GetAlbumArtEmbedded(TM_Item[TrackMode].RawPath, 0);
break;
default:
g_img = gdi.Image(NC_Cover);
break;
}
GetRatio(g_img);
}

//--------- Album Info
GetInfoTitle = new Array(99);
GetInfoTime = new Array(99);
GetInfoRating = new Array(99);
var DATMax = 0;
var AlbumRating = 0;

function AlbumInfo() {
var DATAlbum = fb.TitleFormat("$replace(%album artist% - [%album%][' {CD: '%discnumber%'/'%totaldiscs%'}'] - %date%,'[','<',']','>')");
var DATTitle = fb.TitleFormat("%tracknumber% - Title");
var VALTitle = fb.TitleFormat("%title%[ - %titleversion%]");
var DATTime = fb.TitleFormat("%tracknumber% - Time");
var VALTime = fb.TitleFormat("%length_seconds%");
var DATFile = fb.TitleFormat("%tracknumber% - $replace(%_path%,%filename_ext%,)");
var VALFile = fb.TitleFormat("$meta(rating)");
// Max Track Info
DATMax = Number(utils.ReadINI(DAT_File, DATAlbum.eval(), "DATMax",0));
if (DATMax < Number(fb.TitleFormat("%tracknumber%").eval())) {
DATMax = Number(fb.TitleFormat("%tracknumber%").eval());
utils.WriteINI(DAT_File, DATAlbum.eval(), "DATMax", DATMax);
}
// Save Track Info
utils.WriteINI(DAT_File, DATAlbum.eval(), DATTitle.eval(), VALTitle.eval());
utils.WriteINI(DAT_File, DATAlbum.eval(), DATTime.eval(), VALTime.eval());
utils.WriteINI(DAT_File, DATAlbum.eval(), DATFile.eval(), VALFile.eval());
// Get Album Info
var AlbumTime = 0;
var AlbumTimeRating = 0;
var G_Title = "";
var G_Time = "";
var G_File = "";
var j = "";
for (var i = 1; i <= DATMax; i++) {
j = (i <= 9) ? "0" + i : i;
G_Title = j + " - Title";
G_Time = j + " - Time";
G_File = j + " - " + fb.TitleFormat("$replace(%_path%,%filename_ext%,)").eval();
GetInfoTitle[i] = utils.ReadINI(DAT_File, DATAlbum.eval(), G_Title,"No Title");
GetInfoTime[i] = Number(utils.ReadINI(DAT_File, DATAlbum.eval(), G_Time,0));
GetInfoRating[i] = Number(utils.ReadINI(DAT_File, DATAlbum.eval(), G_File,0));
GetInfoRating[i] = (GetInfoRating[i]<0) ? 1 : (GetInfoRating[i]<=5) ? GetInfoRating[i] :  1;
AlbumTime += GetInfoTime[i];
AlbumTimeRating += GetInfoTime[i] * GetInfoRating[i];
}
AlbumRating = Math.round(100 * AlbumTimeRating / AlbumTime) / 100;
AlbumRating = (AlbumRating<0) ? "" : (AlbumRating<=5) ? AlbumRating :  ""
}



//----------------------------------------------------------------------------
//------ Setup Menu
var MFlag = {
Enabled: 0x00000000,
String: 0x00000000,
Unchecked: 0x00000000,
Grayed: 0x00000001,
Disabled: 0x00000002,
Bitmap: 0x00000004,
Checked: 0x00000008,
Popup: 0x00000010,
MenuBarBreak: 0x00000020,
MenuBreak: 0x00000040,
OwnerDraw: 0x00000100,
Separator: 0x00000800,
RightJustify: 0x00004000
};

function ShowSetup(x,y) {
var SelectId = (ArtCheck[ArtId] == 1) ? ArtId : ArtCheck[0];
var _Menu = window.CreatePopupMenu();
var ret;

_Menu.AppendMenuItem(MFlag.String, 01, "Front");
_Menu.AppendMenuItem(MFlag.String, 02, "Back");
_Menu.AppendMenuItem(MFlag.String, 03, "Disc");
_Menu.AppendMenuItem(MFlag.String, 04, "Icon");
_Menu.AppendMenuItem(MFlag.String, 05, "Artist");
_Menu.AppendMenuItem(MFlag.String, 06, "Embedded");
_Menu.AppendMenuSeparator();
_Menu.AppendMenuItem(MFlag.Disabled, 10, "Save default");
_Menu.AppendMenuItem(MFlag.String, 11, "Front");
_Menu.AppendMenuItem(MFlag.String, 12, "Back");
_Menu.AppendMenuItem(MFlag.String, 13, "Disc");
_Menu.AppendMenuItem(MFlag.String, 14, "Icon");
_Menu.AppendMenuItem(MFlag.String, 15, "Artist");
_Menu.AppendMenuItem(MFlag.String, 16, "Embedded");

_Menu.CheckMenuRadioItem(01, 06, SelectId);
_Menu.CheckMenuRadioItem(11, 16, ArtIdS + 10);

CheckImage(TrackMode);
for (var i = 1; i <= 6; i++) {
if (ArtCheck[i] == 0) _Menu.EnableMenuItem(i, MFlag.Grayed);
}

ret = _Menu.TrackPopupMenu(x,y);
if (ret == 0) return;
if (ret >= 01 && ret <= 06) ArtId = ret;
if (ret >= 11 && ret <= 16) {
ArtIdS = ret - 10;
utils.WriteINI(INI_File, "Album Art", "StandardArtId", ArtIdS);
}
}

//----------------------------------------------------------------------------
//------ Callback functions
//--------- Paint
// Called when window is ready to draw
// gr - Refer to IGdiGraphics
function on_paint(gr) {
SelectImage();

// Draw Background
gr.FillSolidRect( 0, 0, ww, wh, RGB(016,016,024));

// Draw Cover
GetRatio(g_img);
gr.DrawImage( g_img, (ww / 2) - (iw / 2), wh-ih, iw, ih, 0, 0, iws, ihs);

AlbumInfo();
gr.FillSolidRect( 0, 0, ww, 70 + DATMax * 12, RGBA(016,016,024,128));
gr.DrawString(fb.TitleFormat("%album artist%").eval(),  font_Artist,  c_Artist, 0, 2, ww, 16, StrFmt_Artist);
gr.DrawString(fb.TitleFormat("[%album%][' {CD: '%discnumber%'/'%totaldiscs%'}']").eval(),  font_Album,  c_Album, 0, 16, ww, 16, StrFmt_Album);
gr.DrawString(fb.TitleFormat("'('[%original_date%'  ~  ']%date%')   '").eval(),  font_Date,  c_Date, 0, 33, ww, 10, StrFmt_Date);
gr.DrawString(AlbumRating,  font_Rating,  c_Rating, 0, 42, ww, 16, StrFmt_Rating);
for (var i = 1; i <= DATMax; i++) {
if (Math.floor(i / 2) == i / 2) {
gr.FillSolidRect( 0, 55 + i *14, ww, 14, RGBA(096,096,096,128));
} else {
gr.FillSolidRect( 0, 55 + i *14, ww, 14, RGBA(016,016,024,128));
}
j = (i <= 9) ? "0" + i : i;
if (fb.TitleFormat("%tracknumber%").eval() == j) {
gr.DrawString(j + ". >",  font_Number,  c_NumberPlay, 2, 55 + i *14, 30, 14, StrFmt_Number);
} else {
gr.DrawString(j + ".",  font_Number,  c_Number, 2, 55 + i *14, 24, 14, StrFmt_Number);
}
gr.DrawString(GetInfoTitle[i],  font_Title,  c_Title, 26, 55 + i *14, ww-76, 14, StrFmt_Title);
gr.DrawString(TimeFmt(GetInfoTime[i]),  font_Time,  c_Time, ww-45, 55 + i *14, 40, 14, StrFmt_Time);
}
}

//--------- Window
function on_size(){
window.Repaint();
}

//--------- Playback
// cmd: (integer, begin with 0): default, play, next, prev, settrack, rand, resume
//function on_playback_starting(cmd, is_paused) {
// if (PFCState == PFCI.OffDuringPlaying) fb.PlaybackFollowCursor = false;
// window.Repaint();
//}

// reason: (integer, begin with 0): user, eof, starting_another, shutting_down
function on_playback_stop(reason) {
if (reason != 2) {
fb.PlaybackFollowCursor = true;
TrackMode =  TMI.FollowCurser;
}
window.Repaint();
}

// metadb - Refer to IFbMetadbHandle
function on_playback_new_track(metadb) {
window.Repaint();
}

//--------- Focus
// Called when playlist focus has been changed
// For those who what to implement "follow cursor"
function on_item_focus_change() {
window.Repaint();
}

//--------- Mouse
// mask: see Flags.txt for more details
function on_mouse_lbtn_down(x,y){
ShowSetup(x,y);
window.Repaint();
}

//--------- metadb
// [1.1.3] New: Called when metadb contents change. (Or, one of display hook component requests display update).
// Cooperated with window.WatchMetadb() and window.UnWatchMetadb()
// metadb: The same metadb as in window.WatchMetadb(metadb)
// fromhook: boolean, set to true when actual file contents haven't changed but one of metadb_display_field_provider
//   implementations requested an update so output of metadb_handle::format_title() etc has changed.
function on_metadb_changed(metadb, fromhook) {
window.Repaint();

}

//EOF


Sobald ein Track angespielt wird werden Titel Spielzeit und Rating in eine DAT-Datei geschrieben (ACHTUNG DER UNTERORDNER s.o.) zur Identifizierung wird auch noch zwingend die Tracknummer benötigt (vielleicht bekomme ich oder jemand anderes das auch noch eleganter und Idiotensicherer hin). Dann wird wie oben schon angedeutet das Trackrating mit der Tracklänge multipliziert und anschliesend nach Aufsummierung aller Trackzeitratings das ganze durch die Albumspielzeit dividiert. Auf Sterne habe ich zugunsten der numerischen Anzeige verzichtet um so auch 2 Nachkommastellen berücksichtigen zu können, dies dürfte aber auch leicht abwandelbar sein.

Um die Datenbank zu füllen muss jeder Titel einmal angespielt werden (habe ich mit dem Preview-Pluckin > je 2 sec pro Titel innerhalb von 8 Stunden für knapp 9000 Dateien erledigt gehabt). Sollte Ein Rating Tag nicht gesetzt sein wird dieser mit 1 angenommen, akzeptiert werden Ratings von 0 bis 5. Gespeichert werden die Informationen in der DAT-Datei wie folgt:

Zitat
[Genesis - Selling England By The Pound - 1985]
DATMax=8
01 - Title=Dancing With The Moonlit Knight
01 - Time=485
01 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=5
02 - Title=I Know What I Like (In Your Wardrobe)
02 - Time=248
02 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=4
03 - Title=Firth Of Fifth
03 - Time=578
03 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=5
04 - Title=More Fool Me
04 - Time=193
04 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=3
05 - Title=The Battle Of Epping Forest
05 - Time=709
05 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=4
06 - Title=After The Ordeal
06 - Time=257
06 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=3
07 - Title=The Cinema Show
07 - Time=664
07 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=4
08 - Title=Aisle Of Plenty
08 - Time=96
08 - E:\Archiv\Audio\G  H  I\Genesis\(1973 ~ 1985) Selling England By The Pound\=4

Den Dateipfad als Bezeichner für das Rating habe ich gewählt damit zwar jedes Album (bei einheitlichem Tagin der Sammlung) nur einmal in der Datenbank auftaucht, aber eventuelle Sicherheitskopien mit einem anderen Pfad ebenfalls mit aufgenommen werden können. Und so könnte man dann auch sehen ob man nachträglich das eine oder andere Lied doch anders bewertet hatte oder, wenn man ein autotagin über den playcount z.B. realisiert hatte, ob sich das Rating Tag über die Zeit verändert hatte.

Auch kann das Cover gewählt werden welches Angezeigt werden soll (Front, Back, Artist u.s.w.), natürlich per INI-Datei präferierbar, und das ganze mit eine ausweich Variation falls das Defauld Cover nicht verfügbar ist.

Sicherlich mag der Code noch etwas ROH sein da ich wie ich wohl schon mal erwähnte eigentlich mit dem Programmieren nichts zu tuen habe  und ich mir die einzelnen Fragmente zusammenpurzle.

Viel Spaß damit Gruß

TomPro

tedgo

Zitat von: TomPro in 21. Juni 2009, 02:10:28
... Lege also den Ordner 1stStike an und es wird funktionieren, genauso, wie wenn du den Pfad im Script auf --- sagen wir mal --- DarkOne änderst.
Hab ich inzwischen rausgekriegt
Jetzt beginnt sich mir auch der Sinn zu erschließen :)

grimes

Kompliment für Deine Programmierarbeit.

Anmerkung zum Albumrating:
ZitatDann wird wie oben schon angedeutet das Trackrating mit der Tracklänge multipliziert und anschliesend nach Aufsummierung aller Trackzeitratings das ganze durch die Albumspielzeit dividiert.
Damit wichtest Du längere Stücke natürlich höher als kürzere. Das kann man machen. In der Praxis finde ich aber, dass auch ein sehr kurzer grottenschlechter Track zu einer deutlichen Abwertung des gesamten Albums führen müsste. Als Alternative könntest Du jeden Track gleich wichten: Summe(Trackrating)/Zahl der Tracks. Vielleicht kann man sich ja beides anzeigen lassen.

Fragen: Gibt es irgendwelche Performance-Einbußen durch Lese- oder Schreib-Prozesse in die Datenbank? Warum verwendest Du keine "professionelle" Datenbank wie MySQL? Geht das nicht?

TomPro

Zitat von: grimes in 21. Juni 2009, 10:49:11...Als Alternative könntest Du jeden Track gleich wichten: Summe(Trackrating)/Zahl der Tracks. Vielleicht kann man sich ja beides anzeigen lassen...

Das müsse ich hinkriegen, mach mich gleich drann.

Zitat von: grimes in 21. Juni 2009, 10:49:11...Fragen: Gibt es irgendwelche Performance-Einbußen durch Lese- oder Schreib-Prozesse in die Datenbank? Warum verwendest Du keine "professionelle" Datenbank wie MySQL? Geht das nicht?

Weil ich wie schon erwähnt nicht wirklich programmieren kann. Ich habe Ideen suche in Bedienungsanleitung wie Selfhtml von Stefan Münz für JScript oder den beigelegten Hilfstexten oder anderen geposteten Arbeiten nach Lösungen und versuche die sinnvoll zu verknüpfen.

Hatte gerade beim Schreiben ein Dejavue. Jeff Goldblum wurde in die Fliege in etwa gefragt wie er so multidisziplinär sein könne um einen Teletransporter im Alleingang entwickeln zu können, und er sagte sinngemäß das er dies nicht sei, er beauftrage Firmen die im dies oder jenes konstruieren könne und baue dies lediglich zusammen. lol  ;)

Ich habe absolut keine Ahnung von Datenbanken

Gruß TomPro (bis gleich mus mein Script anpassen für das Trackzahlrating)

TomPro

[CUI]

I'll be back

Hier der Code für die Anzeige von, natürlich Wahlweise, AlbumRating gewichtet nach Tracklänge, Trackanzahl oder beidem:

//----------------------------------------------------------------------------
//--- 1stStrike Album Art & Info (by TomPro) v 0.8.1
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//------ Global
//--------- Variable
var INI_File = fb.FoobarPath + "1stStrike\\1stStrike.ini" // Path and Name of the INI Inifile
var DAT_File = fb.FoobarPath + "1stStrike\\albuminfo.dat" // Path and Name of the INI Inifile
var NC_Cover = fb.FoobarPath + "1stStrike\\IMG\\NoCover.png" // Path and Name of a No Cover Image
var File_Path = fb.TitleFormat("$directory_path(%path%)") // Path  of a played File
var get_ini_data, g_img;

var AI = { NoCover: 0, Front: 1, Back: 2, Disc: 3, Icon: 4, Artist: 5, Embedded: 6 }
get_ini_data = utils.ReadINI(INI_File, "Album Art", "StandardArtId", AI.Embedded);
var ArtIdS = Number(get_ini_data); //  Kind of Cover Standard
var ArtId = ArtIdS; //  Kind of Cover
var RV = { Length: 1, Number: 2, Either: 3 }
get_ini_data = utils.ReadINI(INI_File, "Album Art", "RatingState", RV.Either);
var RatingState = Number(get_ini_data); //  Kind of Ratingview
var ArtCheck = new Array(6); // Check IDs of existing Cover

var TMI = { NowPlaying: 1, FollowCurser: 2 };
var TrackMode = TMI.FollowCurser;
var TMT = new Array( "Now Playing", "Follow Curser" );
var TM_Item = new Array(2);

//--------- Window
var ww = window.Width; // Height of the Window
var wh = window.Height; // Width of the Window

//--------- Set Color
function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r,g,b,a){ return ((a<<24)|(r<<16)|(g<<8)|(b)); }

//--------- Format Time String
function TimeFmt(t){
var zpad = function(n){
var str = n.toString();
return (str.length<2) ? "0"+str : str;
}
var h = Math.floor(t/3600); t-=h*3600;
var m = Math.floor(t/60); t-=m*60;
var s = Math.floor(t);
if(h>0) return h.toString()+":"+zpad(m)+":"+zpad(s);
return m.toString()+":"+zpad(s);
}

//----------------------------------------------------------------------------
//------ Text Options
//--------- Font
// format : x = gdi.Font("FontName", ptSize, FStyle.Style);
var FStyle = { Normal: 0, Bold: 1, Italic: 2, Underline: 4, Strikeout: 8 }

//--------- String Format
//------------ Align
var HAlign = { Left: 0, Center: 1, Right: 2 }
var VAlign = { Top: 0, Middle: 1, Bottom: 2 }

//------------ Trim
var Trim = { No: 0, Chara: 1, Word: 2, ElipsChara: 3, ElipsWord: 4, ElipsPath: 5 }

//------------ Flag
var Flag = {
Rtl: 0x0001,
Vert: 0x0002,
Nofit : 0x0004,
Dispctrl: 0x0020,
Nofallback: 0x0400,
Trailspace: 0x0800,
Nowrap: 0x1000,
Linelimit: 0x2000,
Noclip: 0x4000
}

//------------ Set String Format
function StrFmt(alignH,alignV,trim,flag){ return ((alignH<<28)|(alignV<<24)|(trim<<20)|flag); }

//----------------------------------------------------------------------------
//------ Album Art and Info
//--------- Strings
//------------ Font
var font_Artist = gdi.Font("Zurich Ex BT", 13, FStyle.Normal);
var font_Album = gdi.Font("Tahoma", 13, FStyle.Bold);
var font_Date = gdi.Font("Tahoma", 9, FStyle.Normal);
var font_Rating = gdi.Font("Arial",10, FStyle.Bold);
var font_Number = gdi.Font("Arial", 9, FStyle.Bold);
var font_Title = gdi.Font("Zurich Ex BT", 10, FStyle.Normal);
var font_Time = gdi.Font("Arial", 10, FStyle.Bold);

//------------ Colors
var c_Artist = RGB(128,128,000);
var c_Album = RGB(255,255,000);
var c_Date = RGB(192,192,000);
var c_Rating = RGB(255,192,192);
var c_Number = RGB(128,192,128);
var c_NumberPlay = RGB(255,128,128);
var c_Title = RGB(128,255,128);
var c_Time = RGB(255,255,096);

//------------ Formats
var StrFmt_Artist = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Album = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Date = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Rating = StrFmt(HAlign.Center, VAlign.Top, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Number = StrFmt(HAlign.Left, VAlign.Middle, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Title = StrFmt(HAlign.Left, VAlign.Middle, Trim.ElipsChara, Flag.Nowrap);
var StrFmt_Time = StrFmt(HAlign.Right, VAlign.Middle, Trim.No, Flag.Nowrap);

//--------- Album Art Ratio
var wr, iw, ih, iws, ihs, irs;

function GetRatio(image) {
ww = window.Width;
wh = window.Height;
wr = ww/(wh); // Ratio of the Windows minus 15 px Head
iws = image.Width; // Source-Width of the Selected Cover
ihs = image.Height; // Source-Height of the Selected Cover
irs = iws/ihs; // Ratio of the Selected Cover

if (wr > irs) {
iw = Math.round(wh * irs); // Width of the Selected Cover
ih = wh; // Height of the Selected Cover
} else {
iw = ww; // Width of the Selected Cover
ih = Math.round(ww / irs); // Height of the Selected Cover
}
}

//--------- Album Art
ActualItem()

function ActualItem() {
TM_Item[TMI.NowPlaying] = fb.GetNowPlaying();
TM_Item[TMI.FollowCurser] = fb.GetFocusItem();
}

function CheckImage(Item) {
var c_img = null;
ActualItem();
if (! TM_Item[Item] ){
for (var i = 6; i >= 0; i--) { ArtCheck[i]  =  0; }
} else {
ArtCheck[0] = 0;
for (var i = 5; i >= 1; i--) {
c_img = utils.GetAlbumArt(TM_Item[Item].RawPath, i-1);
ArtCheck[i] = (c_img) ? 1 : 0;
ArtCheck[0] = (c_img) ? i : ArtCheck[0];
}
c_img = utils.GetAlbumArtEmbedded(TM_Item[Item].RawPath, 0);
ArtCheck[6] = (c_img) ? 1 : 0;
ArtCheck[0] = (c_img) ? 6 : ArtCheck[0];
}
}

function SelectImage() {
TrackMode = (fb.isplaying) ? TMI.NowPlaying: TMI.FollowCurser;
CheckImage(TrackMode);
var SelectId = (ArtCheck[ArtId] == 1) ? ArtId : ArtCheck[0];
switch(SelectId) {
case AI.NoCover:
g_img = gdi.Image(NC_Cover);
break;
case AI.Front:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 0);
break;
case AI.Back:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 1);
break;
case AI.Disc:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 2);
break;
case AI.Icon:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 3);
break;
case AI.Artist:
g_img = utils.GetAlbumArt(TM_Item[TrackMode].RawPath, 4);
break;
case AI.Embedded:
g_img = utils.GetAlbumArtEmbedded(TM_Item[TrackMode].RawPath, 0);
break;
default:
g_img = gdi.Image(NC_Cover);
break;
}
GetRatio(g_img);
}

//--------- Album Info
GetInfoTitle = new Array(99);
GetInfoTime = new Array(99);
GetInfoRating = new Array(99);
var DATMax = 0;
var AlbumRatingLength = 0;
var AlbumRatingNumber = 0;

function AlbumInfo() {
var DATAlbum = fb.TitleFormat("$replace(%album artist% - [%album%][' {CD: '%discnumber%'/'%totaldiscs%'}'] - %date%,'[','<',']','>')");
var DATTitle = fb.TitleFormat("%tracknumber% - Title");
var VALTitle = fb.TitleFormat("%title%[ - %titleversion%]");
var DATTime = fb.TitleFormat("%tracknumber% - Time");
var VALTime = fb.TitleFormat("%length_seconds%");
var DATFile = fb.TitleFormat("%tracknumber% - $replace(%_path%,%filename_ext%,)");
var VALFile = fb.TitleFormat("$meta(rating)");
// Max Track Info
DATMax = Number(utils.ReadINI(DAT_File, DATAlbum.eval(), "DATMax",0));
if (DATMax < Number(fb.TitleFormat("%tracknumber%").eval())) {
DATMax = Number(fb.TitleFormat("%tracknumber%").eval());
utils.WriteINI(DAT_File, DATAlbum.eval(), "DATMax", DATMax);
}
// Save Track Info
utils.WriteINI(DAT_File, DATAlbum.eval(), DATTitle.eval(), VALTitle.eval());
utils.WriteINI(DAT_File, DATAlbum.eval(), DATTime.eval(), VALTime.eval());
utils.WriteINI(DAT_File, DATAlbum.eval(), DATFile.eval(), VALFile.eval());
// Get Album Info
var AlbumTime = 0;
var AlbumTimeRating = 0;
var AlbumNumberRating = 0;
var G_Title = "";
var G_Time = "";
var G_File = "";
var j = "";
for (var i = 1; i <= DATMax; i++) {
j = (i <= 9) ? "0" + i : i;
G_Title = j + " - Title";
G_Time = j + " - Time";
G_File = j + " - " + fb.TitleFormat("$replace(%_path%,%filename_ext%,)").eval();
GetInfoTitle[i] = utils.ReadINI(DAT_File, DATAlbum.eval(), G_Title,"No Title");
GetInfoTime[i] = Number(utils.ReadINI(DAT_File, DATAlbum.eval(), G_Time,0));
GetInfoRating[i] = Number(utils.ReadINI(DAT_File, DATAlbum.eval(), G_File,0));
GetInfoRating[i] = (GetInfoRating[i]<0) ? 1 : (GetInfoRating[i]<=5) ? GetInfoRating[i] :  1;
AlbumTime += GetInfoTime[i];
AlbumTimeRating += GetInfoTime[i] * GetInfoRating[i];
AlbumNumberRating += GetInfoRating[i];
}
AlbumRatingLength = Math.round(100 * AlbumTimeRating / AlbumTime) / 100;
AlbumRatingLength = (AlbumRatingLength<0) ? "" : (AlbumRatingLength<=5) ? AlbumRatingLength :  ""
AlbumRatingNumber = Math.round(100 * AlbumNumberRating / DATMax) / 100;
AlbumRatingNumber = (AlbumRatingNumber<0) ? "" : (AlbumRatingNumber<=5) ? AlbumRatingNumber :  ""
}



//----------------------------------------------------------------------------
//------ Setup Menu
var MFlag = {
Enabled: 0x00000000,
String: 0x00000000,
Unchecked: 0x00000000,
Grayed: 0x00000001,
Disabled: 0x00000002,
Bitmap: 0x00000004,
Checked: 0x00000008,
Popup: 0x00000010,
MenuBarBreak: 0x00000020,
MenuBreak: 0x00000040,
OwnerDraw: 0x00000100,
Separator: 0x00000800,
RightJustify: 0x00004000
};

function ShowSetup(x,y) {
var SelectId = (ArtCheck[ArtId] == 1) ? ArtId : ArtCheck[0];
var _Menu = window.CreatePopupMenu();
var ret;

_Menu.AppendMenuItem(MFlag.String, 01, "Front");
_Menu.AppendMenuItem(MFlag.String, 02, "Back");
_Menu.AppendMenuItem(MFlag.String, 03, "Disc");
_Menu.AppendMenuItem(MFlag.String, 04, "Icon");
_Menu.AppendMenuItem(MFlag.String, 05, "Artist");
_Menu.AppendMenuItem(MFlag.String, 06, "Embedded");
_Menu.AppendMenuSeparator();
_Menu.AppendMenuItem(MFlag.Disabled, 10, "Save default");
_Menu.AppendMenuItem(MFlag.String, 11, "Front");
_Menu.AppendMenuItem(MFlag.String, 12, "Back");
_Menu.AppendMenuItem(MFlag.String, 13, "Disc");
_Menu.AppendMenuItem(MFlag.String, 14, "Icon");
_Menu.AppendMenuItem(MFlag.String, 15, "Artist");
_Menu.AppendMenuItem(MFlag.String, 16, "Embedded");
_Menu.AppendMenuSeparator();
_Menu.AppendMenuItem(MFlag.Disabled, 20, "Ratingview");
_Menu.AppendMenuItem(MFlag.String, 21, "Weight by length of track");
_Menu.AppendMenuItem(MFlag.String, 22, "Weight by number of track");
_Menu.AppendMenuItem(MFlag.String, 23, "Either (length / number)");

_Menu.CheckMenuRadioItem(01, 06, SelectId);
_Menu.CheckMenuRadioItem(11, 16, ArtIdS + 10);
_Menu.CheckMenuRadioItem(21, 23, RatingState + 20);

CheckImage(TrackMode);
for (var i = 1; i <= 6; i++) {
if (ArtCheck[i] == 0) _Menu.EnableMenuItem(i, MFlag.Grayed);
}

ret = _Menu.TrackPopupMenu(x,y);
if (ret == 0) return;
if (ret >= 01 && ret <= 06) ArtId = ret;
if (ret >= 11 && ret <= 16) {
ArtIdS = ret - 10;
utils.WriteINI(INI_File, "Album Art", "StandardArtId", ArtIdS);
}
if (ret >= 21 && ret <= 23) {
RatingState = ret - 20;
utils.WriteINI(INI_File, "Album Art", "RatingState", RatingState);
}
}

//----------------------------------------------------------------------------
//------ Callback functions
//--------- Paint
// Called when window is ready to draw
// gr - Refer to IGdiGraphics
function on_paint(gr) {
SelectImage();

// Draw Background
gr.FillSolidRect( 0, 0, ww, wh, RGB(016,016,024));

// Draw Cover
GetRatio(g_img);
gr.DrawImage( g_img, (ww / 2) - (iw / 2), wh-ih, iw, ih, 0, 0, iws, ihs);

AlbumInfo();
gr.FillSolidRect( 0, 0, ww, 70 + DATMax * 12, RGBA(016,016,024,128));
gr.DrawString(fb.TitleFormat("%album artist%").eval(),  font_Artist,  c_Artist, 0, 2, ww, 16, StrFmt_Artist);
gr.DrawString(fb.TitleFormat("[%album%][' {CD: '%discnumber%'/'%totaldiscs%'}']").eval(),  font_Album,  c_Album, 0, 16, ww, 16, StrFmt_Album);
gr.DrawString(fb.TitleFormat("'('[%original_date%'  ~  ']%date%')   '").eval(),  font_Date,  c_Date, 0, 33, ww, 10, StrFmt_Date);
switch(RatingState) {
case RV.Length:
gr.DrawString(AlbumRatingLength,  font_Rating,  c_Rating, 0, 42, ww, 16, StrFmt_Rating);
break;
case RV.Number:
gr.DrawString(AlbumRatingNumber,  font_Rating,  c_Rating, 0, 42, ww, 16, StrFmt_Rating);
break;
case RV.Either:
gr.DrawString(AlbumRatingLength + " / " + AlbumRatingNumber,  font_Rating,  c_Rating, 0, 42, ww, 16, StrFmt_Rating);
break;
default:
gr.DrawString(AlbumRatingLength + " / " + AlbumRatingNumber,  font_Rating,  c_Rating, 0, 42, ww, 16, StrFmt_Rating);
break;
}
for (var i = 1; i <= DATMax; i++) {
if (Math.floor(i / 2) == i / 2) {
gr.FillSolidRect( 0, 55 + i *14, ww, 14, RGBA(096,096,096,128));
} else {
gr.FillSolidRect( 0, 55 + i *14, ww, 14, RGBA(016,016,024,128));
}
j = (i <= 9) ? "0" + i : i;
if (fb.TitleFormat("%tracknumber%").eval() == j) {
gr.DrawString(j + ". >",  font_Number,  c_NumberPlay, 2, 55 + i *14, 30, 14, StrFmt_Number);
} else {
gr.DrawString(j + ".",  font_Number,  c_Number, 2, 55 + i *14, 24, 14, StrFmt_Number);
}
gr.DrawString(GetInfoTitle[i],  font_Title,  c_Title, 26, 55 + i *14, ww-76, 14, StrFmt_Title);
gr.DrawString(TimeFmt(GetInfoTime[i]),  font_Time,  c_Time, ww-45, 55 + i *14, 40, 14, StrFmt_Time);
}
}

//--------- Window
function on_size(){
window.Repaint();
}

//--------- Playback
// cmd: (integer, begin with 0): default, play, next, prev, settrack, rand, resume
//function on_playback_starting(cmd, is_paused) {
// if (PFCState == PFCI.OffDuringPlaying) fb.PlaybackFollowCursor = false;
// window.Repaint();
//}

// reason: (integer, begin with 0): user, eof, starting_another, shutting_down
function on_playback_stop(reason) {
if (reason != 2) {
fb.PlaybackFollowCursor = true;
TrackMode =  TMI.FollowCurser;
}
window.Repaint();
}

// metadb - Refer to IFbMetadbHandle
function on_playback_new_track(metadb) {
window.Repaint();
}

//--------- Focus
// Called when playlist focus has been changed
// For those who what to implement "follow cursor"
function on_item_focus_change() {
window.Repaint();
}

//--------- Mouse
// mask: see Flags.txt for more details
function on_mouse_lbtn_down(x,y){
ShowSetup(x,y);
window.Repaint();
}

//--------- metadb
// [1.1.3] New: Called when metadb contents change. (Or, one of display hook component requests display update).
// Cooperated with window.WatchMetadb() and window.UnWatchMetadb()
// metadb: The same metadb as in window.WatchMetadb(metadb)
// fromhook: boolean, set to true when actual file contents haven't changed but one of metadb_display_field_provider
//   implementations requested an update so output of metadb_handle::format_title() etc has changed.
function on_metadb_changed(metadb, fromhook) {
window.Repaint();

}

//EOF


@ tedgo
Wenn Du willst kann ich Dir auch den Programtrick zukommen lassen, mit welchem Du auch Unterordner per Script erstellen kannst, hatte den nur vor der Veröffentlichung dieses Scriptes raus genommen; siehe Diskussionsaufruf an anderer Stelle hier im Board.

Viel Spass und ich nehme auch gerne Verbesserungen an, ob ich mich allerdings noch in echte Datenbanken einfuchse weis ich noch nicht

TomPro