[foobar2000]PSSスクリプトの書き方を解説

Panel Stack Splitter(PSS)を使ってfoobar2000のスキンを作るときに、PSSスクリプトをどう書いていったらいいのかを解説します。

解説の仕方を悩んだのですが、解説用に作ったスキンのPSSスクリプトを、機能ごとに説明していく形を取ります。

[foobar2000]PSSスクリプトの書き方を解説
このスキンを使います

ダウンロード

実用性を考えて作っていないので、間違えてメイン環境に上書きしないようにしてください。

コードの説明

Splitter Settings > Scriptタブのコードを上から順番に説明していきます。PSSに加えて、Title formatting(TF)の知識がないと、ちょっと難しいかも知れません。

PSS Splitter Settings Script
このウィンドウです

スキンで使用しているTFと関数

調べるときに役に立つかと思って抜き出してみました。

// TF Functions
$puts
$get
$strcmp
$left
$if
$if3
$ifequal
$or
$add
$sub
$div

// TF Fields
%isplaying%
%ispaused%
%path%
%playback_time_remaining_seconds%
// PSS Functions
$init_ps_glogal
$set_ps_glogal
$gradientrect
$drawrect
$textbutton
$font
$movepanel_c
$showpanel_c
$imageabs

// PSS Fields
%ps_width%
%ps_height%
%ps_foobar2000_path%
%ps_playback_order%

TFは関数が11、変数が4種類。PSSは関数が9、変数が4種類。多いのか少ないのかわかりませんが、これだけ理解すればこの程度のスキンは作ることができる、とも考えられるでしょうか。

title formatting reference (日本語訳)
http://tnetsixenon.xrea.jp/title_formatting.html

Variables

$init_ps_global(panel,0)
$init_ps_global(bgnum,0)

ここから本題に入ります。このコードは、$init_ps_global関数を使って、変数を定義しています。表示中のパネルを別のパネルに切り替えるなどの、スイッチを作るときによく使います。例えば、1行目のpanel変数は、PANEL-2ボタンが押されたときは1になり、PANEL-1ボタンが押されたときは0になります。

Constant

$puts(white,255-255-255-255)

$putsはPSSの関数ではなくTFです。$putsは定数を定義する関数になります。値が変化する変数に対して、定数は値が変化しません。基本的に、スクリプト中に何度も出てくる式や座標などに使われます。後で座標などの値を変更したくなったときに、スクリプト中に散らばっている値を一々変更する手間がなくなるので、大変有用です。このスキンでは、ややこしくなるので1つしか使っていませんが、本来はもっとガッツリ使います。

Background

$if($strcmp(%bgnum%,0),
$set_ps_global(bgcol1,153-0-255-255)
$set_ps_global(bgcol2,108-0-158-255)
)
$if($strcmp(%bgnum%,1),
$set_ps_global(bgcol1,255-0-102-255)
$set_ps_global(bgcol2,158-0-50-255)
)
$if($strcmp(%bgnum%,2),
$set_ps_global(bgcol1,255-153-0-255)
$set_ps_global(bgcol2,158-108-0-255)
)

このコードは、変数bgnumが0、1、2の時それぞれに、変数bgcol1bgcol2を定義するというコードです。背景のグラデーションの色を指定している箇所なので、カラーコードを変更すれば背景の色も変わります。%bgnum%のように、変数を呼び出すときは%変数名%を使います。Variablesの項で$init_ps_global関数を使って変数を定義していましたが、このように$set_ps_globalを使って定義することもできます。

$gradientrect(0,0,%ps_width%,$sub(%ps_height%,100),%bgcol1%,%bgcol2%)

$gradientrectは、グラデーションで塗りつぶした矩形を描画する関数です。上で定義した変数bgcol1bgcol2をここで使用しています。

ちなみに、$gradientrectを使わずに$drawrectにするとベタ塗りの背景に、$drawimageなどの画像表示関数にすると画像を背景に表示することができます。

PSSスクリプトは、上から順番に処理されます。ですので、下記のようなコードがあったとすると、矩形が重なるため2行目の白い矩形だけが見えます。

$drawrect(0,0,%ps_width%,%ps_height%,0-0-0-255,0-0-0-255)
$drawrect(0,0,%ps_width%,%ps_height%,255-255-255-255,255-255-255-255)

Dummy Button

$textbutton(,,,,,,,)

PSSには、起動時にボタンがマウスオン状態になってしまうバグがあります。このコードは、そのバグを回避するためのコードです。致命的なバグではありませんので無くてもいいと思います。このコードは、スクリプト中でボタン関数を使用する前であれば、どこに記述しても効果があります。

Playback Order Buttons

$font(Calibri,9,Bold)

$fontは、$drawtext$textbuttonなどの文字列を表示する関数の、書体を設定する関数です。以降、違う書体を使う場合は、再度設定し直す必要があります。

$if($stricmp($left(%ps_playback_order%,7),'Default'),$textbutton($sub(%ps_width%,100),0,100,16,'Default','Default',COMMAND:'Playback/Order/Repeat (track)';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))
$if($stricmp($left(%ps_playback_order%,14),'Repeat (track)'),$textbutton($sub(%ps_width%,100),0,100,16,'Repeat (track)','Repeat (track)',COMMAND:'Playback/Order/Repeat (playlist)';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))
$if($stricmp($left(%ps_playback_order%,17),'Repeat (playlist)'),$textbutton($sub(%ps_width%,100),0,100,16,'Repeat (playlist)','Repeat (playlist)',COMMAND:'Playback/Order/Random';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))
$if($stricmp($left(%ps_playback_order%,6),'Random'),$textbutton($sub(%ps_width%,100),0,100,16,'Random','Random',COMMAND:'Playback/Order/Shuffle (tracks)';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))
$if($stricmp($left(%ps_playback_order%,16),'Shuffle (tracks)'),$textbutton($sub(%ps_width%,100),0,100,16,'Shuffle (tracks)','Shuffle (tracks)',COMMAND:'Playback/Order/Shuffle (albums)';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))
$if($stricmp($left(%ps_playback_order%,16),'Shuffle (albums)'),$textbutton($sub(%ps_width%,100),0,100,16,'Shuffle (albums)','Shuffle (albums)',COMMAND:'Playback/Order/Shuffle (folders)';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))
$if($stricmp($left(%ps_playback_order%,17),'Shuffle (folders)'),$textbutton($sub(%ps_width%,100),0,100,16,'Shuffle (folders)','Shuffle (folders)',COMMAND:'Playback/Order/Default';REFRESH,fontcolor:255-255-255-255 brushcolor:0-0-0-255,fontcolor:255-255-255-255 brushcolor:0-0-0-255))

よくスキンで使われているオーダー切り替えボタンのコードです。このコードは座標や色を変更すればコピペで使えます。

Preferences Button

$font(Webdings,9)

違う書体を使うので再度設定します。

$textbutton(10,10,20,20,'c','g',COMMAND:'File/Preferences',fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)

プレイヤー左上にある四角のボタンです。このスキンはメニューバーを表示していないので、あった方がいいかと思い付けてみました。PSSはメニューの各項目をコマンドで呼び出すことはできますが、メニューそのものを表示することはできません。

説明用に作ったスキンなので別にメニューやツールバーを表示してもいいのですが、ない方がスキンっぽく見えるんですよね。もっといえば、UI Hacksでウィンドウフレームも非表示にすると更にスキンっぽくなります。(スキンっぽいって何だろう)

Background Change Buttons

$font(Segoe UI Black,12)

書体の再設定です。

$textbutton(10,$div($sub(%ps_height%,140),2),20,20,$ifequal(%bgnum%,0,'●','◌'),$ifequal(%bgnum%,0,'●','●'),SETGLOBAL:bgnum:0;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)
$textbutton(10,$div($sub(%ps_height%,100),2),20,20,$ifequal(%bgnum%,1,'●','◌'),$ifequal(%bgnum%,1,'●','●'),SETGLOBAL:bgnum:1;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)
$textbutton(10,$div($sub(%ps_height%,60),2),20,20,$ifequal(%bgnum%,2,'●','◌'),$ifequal(%bgnum%,2,'●','●'),SETGLOBAL:bgnum:2;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)

プレイヤー左中央の背景切り替えボタンのコードです。選択中の背景に対応するボタンは黒丸、それ以外は白丸を表示するために、テキストの値に条件式を突っ込んでいます。このように、関数内で条件式を使うことで、多少は複雑な処理も行うことができるようになります。コマンドのREFRESHは、何か表示が変更される処理には必須です。フォントカラーの$getは、前述の定数を呼び出すための関数になります。

Backgroundの項で出た$if($strcmp(%bgnum%,0),)$ifequal(%bgnum%,0,,)は、値を文字列として解釈するか、数値として解釈するかの違いがありますが、同じ働きをするようです。本当なら文字列と数値で使い分けるのがセオリーなのだと思いますが、私はthenの処理だけの場合は$ifelseの処理も必要な場合は$ifequalを使うようにしています。($if文は$if(cond,then)という書き方ができるため)

Playback Buttons

$font(Webdings,12)

また書体の再設定です。

$textbutton($sub(%ps_width%,30),$sub(%ps_height%,130),20,20,'4','4',COMMAND:'Playback/Play',fontcolor:$get(white),fontcolor:200-200-200-255)
$textbutton($sub(%ps_width%,60),$sub(%ps_height%,130),20,20,'9','9',COMMAND:'Playback/Previous',fontcolor:$get(white),fontcolor:200-200-200-255)
$textbutton($sub(%ps_width%,90),$sub(%ps_height%,130),20,20,';',';',COMMAND:'Playback/Pause',fontcolor:$get(white),fontcolor:200-200-200-255)
$textbutton($sub(%ps_width%,30),$sub(%ps_height%,160),20,20,':',':',COMMAND:'Playback/Next',fontcolor:$get(white),fontcolor:200-200-200-255)
$textbutton($sub(%ps_width%,30),$sub(%ps_height%,190),20,20,'<','<',COMMAND:'Playback/Stop',fontcolor:$get(white),fontcolor:200-200-200-255)

再生ボタンや停止ボタンなどのプレイバックボタンを表示するコードになります。$textbuttonよりも$imagebuttonが使われることが多いですが、これもよく使われるコードです。

Panel Change Buttons Background

$drawrect(0,$sub(%ps_height%,100),%ps_width%,56,70-70-70-255,70-70-70-255)

$drawrectはベタ塗りの矩形を描画する関数です。このコードは、PANEL-1、PANEL-2と表示されている、パネル切り替えボタンの下地部分ですが、ボタン自体は透明で、この矩形の上に透明のボタンが重なっています。

Panel Change Buttons Indicator

$if($strcmp(%panel%,0),
$drawrect(0,$sub(%ps_height%,100),$div(%ps_width%,2),1,$get(white),$get(white))
)
$if($strcmp(%panel%,1),
$drawrect($div(%ps_width%,2),$sub(%ps_height%,100),$div(%ps_width%,2),1,$get(white),$get(white))
)

パネル切り替えボタンのインジケーターのコードです。panel変数の値によってX座標を変更します。このコードを1行にまとめると下記のようになります。

$drawrect($ifequal(%panel%,0,0,$div(%ps_width%,2)),$sub(%ps_height%,100),$div(%ps_width%,2),1,$get(white),$get(white))

$drawrectは矩形の内側と枠で、高さは2が最低のような気がしますが、高さを1にすると1ピクセルで表示してくれます。(たぶん値が1だと枠は表示されていない)

Panel Change Buttons

$font(Consolas,12)

書体の再設定。

$textbutton(0,$sub(%ps_height%,100),$div(%ps_width%,2),56,'PANEL-1','PANEL-1',SETGLOBAL:panel:0;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-30)
$textbutton($div(%ps_width%,2),$sub(%ps_height%,100),$div(%ps_width%,2),56,'PANEL-2','PANEL-2',SETGLOBAL:panel:1;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-30)

前述した透明のボタンのコードです。

PSSのボタンは、通常の表示とマウスオン時の表示しか設定することができないので、現在どのパネルが表示されているか、何番の背景が表示されているのか、ボタンの見た目で選択状態を確認することができないため、所謂タブを作りたいようなときは別途処理を追加する必要があり、このように若干ややこしいことになってしまいます。

Underbar Background

$drawrect(0,$sub(%ps_height%,40),%ps_width%,40,50-50-50-255,50-50-50-255)

ベタ塗りの矩形描画関数です。位置的には、プレイヤー最下部の濃いグレーの箇所になります。この部分も矩形の上に透明のパネルを重ねています。

Panel Area

$movepanel_c(yts,40,40,$sub($div(%ps_width%,2),40),40)
$movepanel_c(jsplaylist,40,80,$sub($div(%ps_width%,2),40),$sub(%ps_height%,220))
$movepanel_c(ytv,$div(%ps_width%,2),40,$sub($div(%ps_width%,2),40),$sub(%ps_height%,180))
$movepanel_c(ls3,40,40,$sub(%ps_width%,80),$sub(%ps_height%,180))
$movepanel_c(seekbar,0,$sub(%ps_height%,44),%ps_width%,4)
$movepanel_c(st,40,$sub(%ps_height%,40),$sub(%ps_width%,80),40)
$movepanel_c(shpeck,$sub(%ps_width%,36),$sub(%ps_height%,36),32,32)

各パネルの表示位置や領域を指定するコードです。ボタンや背景などの装飾は無しで、単にタイル状にパネルを表示したいだけなら、このコードだけで済みます。

Splitter Settings > Panellistでも同じことができるのですが、後で値を変更したくなったときに非常に手間です。断然スクリプトでやった方が楽だと思います。

PSS Splitter Settings Panellist
Panellistでも同じことができます

また、シークバーを別のプラグインに変更する場合を例に取ると、既存のシークバーパネルを削除し新しいシークバーパネルを追加したら、あとはCaptionを同じseekbarとすれば変更が完了します。私はPanellistでは、Caption決めとForced layoutのチェックだけしか行いません。

Panel Display State

$if($strcmp(%panel%,0),
$showpanel_c(ls3,0)
$showpanel_c(ytv,1)
$showpanel_c(yts,1)
$showpanel_c(jsplaylist,1)
)
$if($strcmp(%panel%,1),
$showpanel_c(ytv,0)
$showpanel_c(yts,0)
$showpanel_c(jsplaylist,0)
$drawrect(40,40,$sub(%ps_width%,80),$sub(%ps_height%,180),0-0-0-20,0-0-0-20)
$showpanel_c(ls3,1)
)

各パネルの表示状態を指定するコードになります。複数のパネルを切り替えるスキンでは、このように変数を使います。全てのパネルの表示/非表示状態を指定しないと、不具合が起こりやすいです。

たくさんのパネルを表示しようとすると、表示状態を指定するのが大変なので、PSSにPSSを重ねたくなることがあると思います。私も以前は重ねていたのですが、これをやると色々と弊害が生じるので、できるだけ重ねないようにすることをおすすめします。

途中に入っている$drawrectは歌詞表示の下地です。ここも矩形の上に、背景を透明にしたLyric Show Panel 3を重ねています。背景を透過させたスキンは、このように背景を透明にできるパネルを上に重ねると作ることができます。

余談ですが、恐らくバグだと思いますが、$drawrectは内側と枠の色を同じにしても枠が少し濃くなるようです。

Cover

$if($or(%isplaying%,%ispaused%),
$if3($imageabs(4,$sub(%ps_height%,36),32,32,%path%,artreader,),$imageabs(4,$sub(%ps_height%,36),32,32,%ps_foobar2000_path%\user-components\foo_jscript_panel\samples\jsplaylist-mod\images\nocover.png))
,
$imageabs(4,$sub(%ps_height%,36),32,32,%ps_foobar2000_path%\user-components\foo_jscript_panel\samples\jsplaylist-mod\images\logo.png)
)

プレイヤー左下のアルバムアート表示のコードです。ここは$if文の中に$if3文が入っているので、最初は理解しにくいと思います。処理的には、再生中か一時停止中ならアルバムアートを表示し、該当する画像がなかったら代替画像を表示。再生中でも一時停止中でもない(となると停止時になる)場合にはロゴ画像を表示するという処理です。$imageabs関数が、画像を表示すると共に真偽値も返すという性質を利用しています。このコードも画像のパスや座標などを変更すれば流用できます

Auto Change Background

$if($strcmp(%playback_time_remaining_seconds%,1),
$ifequal(%bgnum%,2,$set_ps_global(bgnum,0),$set_ps_global(bgnum,$add(%bgnum%,1))))

このコードはPer Secondタブにあります。次の曲に変わったときに背景を変更するコードです。残り時間1秒になったら、変数bgnumの値を1変更するという処理を行います。秒単位での条件なのでPer Secondタブに記述する必要があります。(説明書の90-92行目を参照)2行目のコードは、変数bgnumを0->1->2->0と回すためのコードです。

応用

コードを改変してみます。

背景を増やす

$if($strcmp(%bgnum%,0),
$set_ps_global(bgcol1,153-0-255-255)
$set_ps_global(bgcol2,108-0-158-255)
)
$if($strcmp(%bgnum%,1),
$set_ps_global(bgcol1,255-0-102-255)
$set_ps_global(bgcol2,158-0-50-255)
)
$if($strcmp(%bgnum%,2),
$set_ps_global(bgcol1,255-153-0-255)
$set_ps_global(bgcol2,158-108-0-255)
)
$if($strcmp(%bgnum%,3),
$set_ps_global(bgcol1,102-255-0-255)
$set_ps_global(bgcol2,50-158-0-255)
)
$if($strcmp(%bgnum%,4),
$set_ps_global(bgcol1,25-0-255-255)
$set_ps_global(bgcol2,29-0-158-255)
)

Backgroundの項で、変数bgnumが3のときの色と、4のときの色を追加します。(背景を2種類増やす場合)

$textbutton(10,$div($sub(%ps_height%,180),2),20,20,$ifequal(%bgnum%,0,'●','◌'),$ifequal(%bgnum%,0,'●','●'),SETGLOBAL:bgnum:0;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)
$textbutton(10,$div($sub(%ps_height%,140),2),20,20,$ifequal(%bgnum%,1,'●','◌'),$ifequal(%bgnum%,1,'●','●'),SETGLOBAL:bgnum:1;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)
$textbutton(10,$div($sub(%ps_height%,100),2),20,20,$ifequal(%bgnum%,2,'●','◌'),$ifequal(%bgnum%,2,'●','●'),SETGLOBAL:bgnum:2;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)
$textbutton(10,$div($sub(%ps_height%,60),2),20,20,$ifequal(%bgnum%,3,'●','◌'),$ifequal(%bgnum%,3,'●','●'),SETGLOBAL:bgnum:3;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)
$textbutton(10,$div($sub(%ps_height%,20),2),20,20,$ifequal(%bgnum%,4,'●','◌'),$ifequal(%bgnum%,4,'●','●'),SETGLOBAL:bgnum:4;REFRESH,fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)

Background Change Buttonsの項で、変数bgnumを3にするボタンと、4にするボタンを追加します。

$if($strcmp(%playback_time_remaining_seconds%,1),
$ifequal(%bgnum%,4,$set_ps_global(bgnum,0),$set_ps_global(bgnum,$add(%bgnum%,1))))

Auto Change Backgroundの項で、変数bgnumが、0->1->2->3->4->0と回るようにコードを変更します。

[foobar2000]PSSスクリプトの書き方を解説 背景と切り替えボタンのみを表示した画像
背景と切り替えボタンのみを表示した画像

下部の黒い部分は、本来パネル切り替えボタンとかが表示されている部分です。何も色を指定しないと、BehaviourタブのChange colourで選択した色が表示されます。(Custom background colourにチェックが入っている必要があります)隣のDefault fontボタンで選択した書体は、$font関数で書体を指定しなかった場合に表示されます。

Splitter Settings Behaviourタブ
Behaviourタブ

定数に入れられる値

$puts(command,COMMAND:'File/Preferences')
$textbutton(15,15,15,15,'c','g',$get(command),fontcolor:$get(white) brushcolor:0-0-0-0,fontcolor:$get(white) brushcolor:0-0-0-0)

こんな感じで、定数にはコマンドも入ります。意味はないですが、%ps_playback_order%なんかも定数に入ります。コンマが含まれるとダメなので関数は入りません。私は$subとか$divとかの式をよく定数にします。

お知らせ

現在お知らせはありません。

最近の投稿

シェア