Содержание

Создание интерфейса на основе Panel Stack Splitter плагина

Введение

Долго расписывать не буду, но вкратце всё же скажу зачем написал эту статью.
Многие (в том числе и я ;-)), установив себе «чистую» версию Foobar - не удовлетворены его внешним видом.
Поиски более «симпатичного» вида плеера приводят их к установке более красивых|функциональных сборок.
И после некоторого времени использования «сборки» нам начинает чего-то не хватать в «сборке», либо наоборот есть что-то что не используется вовсе, а иногда даже и мешает.
Здесь то и возникают проблемы (особенно у тех кто с Английским языком на «ТЫ») так как инструкци если и есть к плагинам, то они на английском (а некоторые вовсе на японском).
Это и становится причиной того, что появляются неудобства при переделывании плеера «под себя».

Инструкция предназначена для тех, кто не испугался (на первый взгляд) замысловато-непонятных скриптов и всё же решился сделать свой
Собственный интерфейс для плеера Foobar2000

С чего начать

Первое, что нужно сделать - это :

  1. Определиться (хотя бы примерно) каким Вы представляете внешний вид Вашего будущего плеере и каким функционалом он должен обладать
  2. Установить сам плеер (я бы рекомендовал версию 0.9.6.9 - так как версия 1.0 пока ещё на стадии бета-тестирования)
  3. Почитать инструкцию к PSS
  4. Добавить в папку components плагины:

Добавление основной панели PSS

PreferencesDisplayColumns UI → вкладка Layout

<box 65% round orange|[Result]:>На данном этапе мы создали основу на которой и будем подбирать и размещать нужные нам панели </box>

Добавление панелей в PSS

И так приступим к выбору и подключению панелей, которые нам нужны будут в конфиге.
Сделать это можно 2-мя способами:

Первый способ

PreferencesDisplayColumns UI → вкладка Layout

  1. в окошке ниже имени пресета видим «Panel Stack Splitter»
  2. жмём на нём ПКМ 1)Insert panel → из нижеследующих вкладок подбираем необходимые панели
    • Panels → тут выбираем к примеру :::
      • Artwork view
      • Item details
      • Item properties
      • Playlist switcher
    • Playlist Views
      • NG Playlist

Так должен будет выглядеть наш список панелей:


Второй способ

ПКМ 2) на поле плеера → Add panel

Аналогично тому как мы набирали панели в первом способе, можно набрать список панелей и этим способом (но он менее нагляден для начального понимания)

<box 65% round orange|[Result]:>Панели подобраны. Теперь приступим к их размещению. </box>

Размещение панелей

По умолчанию панели разместились с горизонтальным смещением относительно друг друга.

Таковое размещение панелей задано по умолчанию для PSS 3)
Приступим к настройке отображения панелей.
Щелкнув ПКМ на свободном от панелей месте Foobar или на панели Artwork view, Item details или Item properties → выбираем пункт Splitter Settings… <box 65% round red|Attention !>Не все панели содержат в контекстных меню ПКМ пункт Splitter Settings….
Это нужно запомнить.</box>

Для ясности рассмотрим из чего состоит и за что отвечает вкладка PanelList.

  1. В левой части отображен список панелей, которые мы добавили для их последующего конфигурирования. Каждой панели соответствует свое имя, которое можно изменить в поле Caption:
  2. Ниже списка панелей есть пункт Panel placement mode: с вариантами
    • Horizontal - горизонтальное размещение панелей относительно друг друга
    • Vertical - вертикальное расположение панелей относительно друг друга
  3. Параметр Size отвечает за размер отображаемой панели,
  4. Блок правее списка панелей активируется для каждой панели отдельно включением значения Forced layout.
    • Use percentage value - этот параметр включает процентное позиционирование left, Top, width, height параметров (по умолчанию координаты и размеры задаются в пикселях [PIXEL])
    • Enable padding settings - включение отступов между панелями согласно значений заданных в блоке Padding

Для того чтобы отобразить панели согласно нашим требованиям - нужно активировать для всех панелей из списка Panel List, пункт Forced layout.

Нажав APPLY все панели исчезли из отображения, так как мы не задали координаты для их отображения.
Выбрав, к примеру, панель Artwork view - зададим ей координаты

left   : 0
Top    : 0
width  : 256
height : 256

В результате получаем статическое отображение панели Artwork view в левом (left=0) верхнем (Top=0) углу с размерами 128 на 128 пиксел.

Далее отобразим к примеру Item details задав для неё координаты

left   : 256
Top    : 0
width  : $sub(%ps_width%,512)
height : 256

По аналогии зададим параметры для остальных панелей:

Item properties

left   : 0
Top    : 256
width  : 256
height : $sub(%ps_height%,286)

Playlists

left   : $sub(%ps_width%,256)
Top    : 0
width  : 256
height : 256

Playlist

left   : 256
Top    : 256
width  : $sub(%ps_width%,256)
height : $sub(%ps_height%,286)

Высоту (height) для панелей Item properties и Playlist специально сделали на 30 пикселей меньше.
Здесь мы добавим кнопки управления плеером. <box 65% round orange|Result>Вот и разместили все панели.</box>

Кнопки управления (текстовые)

Для создания кнопок переходим во вкладку Script
В части PerTrack пишем скрипты для наших кнопочек.
Используем для этого функцию $textbutton(x,y,w,h,text,mover_text,command,options1,options2)

x - координата начала по горизонтали
y - координата начала по вертикали
w - ширина кнопки
h - высота кнопки

text - текст отображаемый на кнопке
mover_text - текст отображаемый на кнопке при наведении «мышки» на неё

command - комманда, которая будет выполняться при нажатии на кнопку

options1 - опции отображения кнопки
options2 - опции отображения кнопки, при наведении «мышки» на неё

Рассмотрим на примере как будет выглядеть кнопка Play

$textbutton(120,$sub(%ps_height%,25),50,20,Play,Play,COMMAND:Playback/Play,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)

Вставляем код в вкладку PerTrack и видим в нижней части прямоугольную кнопку с текстом Play.

Для наглядности и большего понимания посмотрим по отдельности каждый фрагмент кода текстовой кнопки $textbutton(…).
x=120 → координата начала по горизонтали
y=$sub(%ps_height%,25) → координата начала по вертикали
w=50 → ширина кнопки
h=20 → высота кнопки

text:Play → текст отображаемый на кнопке
mover_text:Play → текст отображаемый на кнопке при наведении «мышки» на неё

command:COMMAND:Playback/Play → комманда, которая будет выполняться при нажатии на кнопку

options1:fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0 → опции отображения кнопки
options2:fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0 → опции отображения кнопки, при наведении «мышки» на неё

Аналогично создаем остальные кнопки.
Ниже пример готового набора основных кнопок управления воспроизведением:

//----Кнопки управления воспроизведением----//
$textbutton(20,$sub(%ps_height%,25),50,20,Previous,Previous,COMMAND:Playback/Previous,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)
$textbutton(70,$sub(%ps_height%,25),50,20,Stop,Stop,COMMAND:Playback/Stop,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)
$textbutton(120,$sub(%ps_height%,25),50,20,Play,Play,COMMAND:Playback/Play,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)
$textbutton(170,$sub(%ps_height%,25),50,20,Pause,Pause,COMMAND:Playback/Pause,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)
$textbutton(220,$sub(%ps_height%,25),50,20,Next,Next,COMMAND:Playback/Next,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)
$textbutton(290,$sub(%ps_height%,25),50,20,<<,<<<,COMMAND:Playback/Seek back by 30 seconds,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)
$textbutton(340,$sub(%ps_height%,25),50,20,>>,>>>,COMMAND:Playback/Seek ahead by 30 seconds,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)

Просто скопируйте в PerTrack ВЕСЬ код примера и в нижней части плеера появятся 7 кнопочек.

<box 80% round orange|Hint>Как и во многих языках программирования, строки начинающиеся с // двух «слешей» (косые черты) являются комментариями.
PSS (и многие другие панели) их не обрабатывает. </box>

Кроме кнопок с командами управления в PSS можно создавать кнопки с функционалом доступным для выбора из главного меню (File,Edit,View,…).
Полный список этих команд можно получить выбрав под блоком PerTrack в выпадающем меню пункт Menu Command и нажав кнопку _ _ list _ _.
Щелкнув на нужной команде – она будет добавлена в PerTrack в позицию, в которой находился курсор в момент выбора. Рассмотрим на примере создания кнопки вызова настроек плеера Preferences:
Создадим в PerTrack кнопку без комманды

$textbutton(400,$sub(%ps_height%,25),50,20,Pref-ces,Pref-ces,COMMAND:,fontcolor:64-64-64 brushcolor:192-192-192-128 pencolor:0-0-0,fontcolor:2-22-2-232 brushcolor:92-92-152-128 pencolor:0-0-0)

В результате мы получили вот такой внешний вид плеера: Верхний тулбар (toolbar) я отключил специально, чтобы не отвлекал он в процессе конфигурирования.

Кнопки управления (графические)

Кроме текстовых кнопок в PSS можно сделать графическое оформление кнопок.
По сути - каждую кнопочку можно отобразить графическим файлом.
$imagebutton(x,y,w,h,path,mover_path,command,options1,options2)

Синтакс команды аналогичен текстовой кнопке $textbutton(), отличие только в том, что вместо text и mover_text мы указываем путь к картинке path и mover_path и списком опций для options1,options2

Путь может быть как явно инициализирован:

С:\Program Files\foobar2000\images\button_play.png

так и косвенно:

%ps_foobar2000_path%\images\button_play.png

Косвенная инициализация более удобна при создании portable конфигурации плеера.

Отмечу, что картинка будет автоматически подогнана под ширину w и высоту h кнопки.
Потому, для создания квадратной кнопки нужно выбирать квадратную картинку для сохранения пропорций при отображении.

Промотка и громкость

Явно бросается в глаза нехватка полосы промотки трека (Seekbar) и регулятора громкости (Volume), хотя громкость не всем нужна по причине недоверия ей из-за влияния на качество воспроизведения.
Но всё же рассмотрим, как можно реализовать эти два регулятора с помощью WSH панели.
Для этого:

После добавления, для удобства переименуем Caption этих панелей например в WSH Seekbar и WSH Volume и разместим их таким же способом, как было описано выше.

Как пример приведу координаты и размеры:

WSH Seekbar

left   : 460
Top    : $sub(%ps_height%,25)
width  : $sub(%ps_width%,600)
height : 20

WSH Volume

left   : $sub(%ps_width%,130)
Top    : $sub(%ps_height%,25)
width  : 120
height : 20

Панели размещены, но пока они обе являются регуляторами громкости.

Пример кода Seekbar для WSH

Чтобы преобразовать среднюю (более длинную) WSH панель из регулятора громкости в промотку делаем следующие махинации: :-)

Например такой:

// Flags, used with GdiDrawText
// For more information, see: http://msdn.microsoft.com/en-us/library/dd162498(VS.85).aspx
var DT_TOP = 0x00000000;
var DT_LEFT = 0x00000000;
var DT_CENTER = 0x00000001;
var DT_RIGHT = 0x00000002;
var DT_VCENTER = 0x00000004;
var DT_BOTTOM = 0x00000008;
var DT_WORDBREAK = 0x00000010;
var DT_SINGLELINE = 0x00000020;
var DT_EXPANDTABS = 0x00000040;
var DT_TABSTOP = 0x00000080;
var DT_NOCLIP = 0x00000100;
var DT_EXTERNALLEADING = 0x00000200;
var DT_CALCRECT = 0x00000400;
var DT_NOPREFIX = 0x00000800;
var DT_INTERNAL = 0x00001000;
var DT_EDITCONTROL = 0x00002000;
var DT_PATH_ELLIPSIS = 0x00004000;
var DT_END_ELLIPSIS = 0x00008000;
var DT_MODIFYSTRING = 0x00010000;
var DT_RTLREADING = 0x00020000;
var DT_WORD_ELLIPSIS = 0x00040000;
var DT_NOFULLWIDTHCHARBREAK = 0x00080000;
var DT_HIDEPREFIX = 0x00100000;
var DT_PREFIXONLY = 0x00200000;

function RGB(r,g,b){ return (0xff000000|(r<<16)|(g<<8)|(b)); }

var g_font = gdi.Font("Tahoma", 12, 1);
var g_drag = 0;
var g_drag_seek = 0;
var tfo = fb.TitleFormat("$if(%ispaused%,PAUSE,  )  %playback_time%                of           %length%    '('$max(0,$left($muldiv(%playback_time_seconds%,1000,%length_seconds%),$sub($len($muldiv(%playback_time_seconds%,1000,%length_seconds%)),1)))'.'$right(  $muldiv(%playback_time_seconds%,1000,%length_seconds%),1)'%)'               REM: %playback_time_remaining%");
    

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);
}

function on_paint(gr){
  var txt = "";
  var pos =0;
          
  if(fb.PlaybackTime > 0){
      if(g_drag){
          pos = window.Width * g_drag_seek;
          txt = "Seek " + TimeFmt(g_drag_seek * fb.PlaybackLength) + " / " + TimeFmt(fb.PlaybackLength);
      }
      else{
          pos = window.Width * (fb.PlaybackTime / fb.PlaybackLength);
          txt = tfo.Eval();
      }

  }else
  {
  txt = "Playback Stopped";
  }
  
  
  gr.FillGradRect(  0, 0,    pos, window.Height, 90, RGB(60,10,210), RGB(4,4,93));
  gr.FillGradRect(pos, 0, window.Width-pos, window.Height, 90, RGB(00,00,32), RGB(10,10,10));
  gr.GdiDrawText(txt, g_font, RGB(50,250,50), 0, 0, window.Width, window.Height, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  gr.DrawRect(0,0, window.Width-1, window.Height-1, 1.0, RGB(150,150,150));
}

function on_mouse_lbtn_down(x,y){
  g_drag = 1;
}

function on_mouse_lbtn_up(x,y){
  if(g_drag){
      g_drag = 0;
      g_drag_seek = x / window.Width;
      g_drag_seek = (g_drag_seek<0) ? 0 : (g_drag_seek<1) ? g_drag_seek : 1;
      fb.PlaybackTime = fb.PlaybackLength * g_drag_seek;
  }
}

function on_mouse_move(x,y){
  if(g_drag){
      g_drag_seek = x / window.Width;
      g_drag_seek = (g_drag_seek<0) ? 0 : (g_drag_seek<1) ? g_drag_seek : 1;
      window.Repaint();
  }
}

function on_playback_time(time){
  window.Repaint();
}

function on_playback_stop(){
      window.Repaint();
}

function on_playback_starting(cmd, paused){
	window.Repaint();
}
function on_playback_new_track(info){
  window.Repaint();
}
//EOF

Расматривать и комментировать детали кода не стану - так как для этого уже совсем другая тема нужна. Но рассмотрев код - Вы и сами сможете разобраться как он работает и что за что отвечает в нем.

В результате получили такой вид панели управления:

<box 65% round orange|Result>На данном этапе пока остановимся.
Но в планах у меня есть ещё расширить статью и рассмотреть как реализовуются переключатели, информеры, и т.д. с помощью PSS.
Если возникли вопросы - задаем их в теме Panel Stack Splitter (foo_uie_panel_splitter)
Творческого вдохновения всем!!!
C уважением Izotop</box>

1) , 2) , 4)
ПКМ - это щелчек Правой Кнопки Мыши ;-)
3)
Panel Stack Splitter