iobroker.squeezeboxrpc 2.0.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -18
- package/admin/i18n/de.json +7 -0
- package/admin/i18n/en.json +7 -0
- package/admin/i18n/es.json +7 -0
- package/admin/i18n/fr.json +7 -0
- package/admin/i18n/it.json +7 -0
- package/admin/i18n/nl.json +7 -0
- package/admin/i18n/pl.json +7 -0
- package/admin/i18n/pt.json +7 -0
- package/admin/i18n/ru.json +7 -0
- package/admin/i18n/uk.json +7 -0
- package/admin/i18n/zh-cn.json +7 -0
- package/admin/jsonConfig.json +36 -0
- package/io-package.json +26 -52
- package/lib/iosbplayer.js +3 -4
- package/lib/iosbserver.js +75 -180
- package/lib/lms/client.js +22 -0
- package/lib/lms/connection.js +104 -0
- package/lib/lms/discovery.js +145 -0
- package/lib/lms/jsonRpcClient.js +139 -0
- package/lib/lms/telnetEventClient.js +122 -0
- package/lib/lms/webSocketClient.js +352 -0
- package/package.json +4 -7
- package/widgets/squeezeboxrpc/build/squeezeboxrpc-dist.js +1 -1
- package/widgets/squeezeboxrpc/build/squeezeboxrpc-dist.js.map +1 -1
- package/lib/squeezenode/squeezeplayer.js +0 -480
- package/lib/squeezenode/squeezerequest.js +0 -273
- package/lib/squeezenode/squeezeserver.js +0 -352
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../myi18n/translations.json", "../js/date.format.js", "../js/sbClasses.js", "../../../package.json", "../js/textImage.js", "../js/widgets/browser.js", "../js/itemConfiguration.js", "../js/widgets/favorites.js", "../js/widgets/players.js", "../js/widgets/buttonplay.js", "../js/widgets/buttonfwd.js", "../js/widgets/buttonrew.js", "../js/widgets/buttonrepeat.js", "../js/widgets/buttonshuffle.js", "../js/volumeUtils.js", "../js/widgets/volumebar.js", "../js/widgets/syncgroup.js", "../js/widgets/playtime.js", "../js/widgets/string.js", "../js/widgets/playlist.js", "../js/widgets/playlistdetail.js", "../js/widgets/number.js", "../js/widgets/datetime.js", "../js/widgets/image.js", "../js/configurationEditor.js", "../js/instanceSelection.js", "../img/add.svg", "../img/delete.svg", "../img/fwd.svg", "../img/menuback.svg", "../img/next.svg", "../img/pause.svg", "../img/play.svg", "../img/repeat0.svg", "../img/repeat1.svg", "../img/refresh.svg", "../img/rew.svg", "../img/shuffle0.svg", "../img/shuffle2.svg", "../img/stop.svg", "../js/svgIcons.js", "../js/squeezeboxrpc.js", "../js/bundle.js"],
|
|
4
|
-
"sourcesContent": ["{\n \"ainstance\": { \"en\": \"SqueezeboxRPC instance\", \"de\": \"SqueezeboxRPC-Instanz\", \"ru\": \"\u042D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440 SqueezeboxRPC\", \"pt\": \"Inst\u00E2ncia SqueezeboxRPC\", \"nl\": \"SqueezeboxRPC-instantie\", \"fr\": \"Instance SqueezeboxRPC\", \"it\": \"Istanza SqueezeboxRPC\", \"es\": \"Instancia SqueezeboxRPC\", \"pl\": \"Instancja SqueezeboxRPC\", \"uk\": \"\u0415\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440 SqueezeboxRPC\", \"zh-cn\": \"SqueezeboxRPC \u5B9E\u4F8B\" },\n \"viewindex\": { \"en\": \"Viewindex\", \"de\": \"Ansichtsindex\", \"ru\": \"\u0418\u043D\u0434\u0435\u043A\u0441 \u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043B\u0435\u043D\u0438\u044F\", \"pt\": \"\u00CDndice da vista\", \"nl\": \"Weergave-index\", \"fr\": \"Index de vue\", \"it\": \"Indice vista\", \"es\": \"\u00CDndice de vista\", \"pl\": \"Indeks widoku\", \"uk\": \"\u0406\u043D\u0434\u0435\u043A\u0441 \u043F\u043E\u0434\u0430\u043D\u043D\u044F\", \"zh-cn\": \"\u89C6\u56FE\u7D22\u5F15\" },\n \"wrapcamelcase\": { \"en\": \"Wrap Camelcase\", \"de\": \"CamelCase umbrechen\", \"ru\": \"\u041F\u0435\u0440\u0435\u043D\u043E\u0441 CamelCase\", \"pt\": \"Quebrar CamelCase\", \"nl\": \"CamelCase afbreken\", \"fr\": \"Renvoyer CamelCase \u00E0 la ligne\", \"it\": \"A capo CamelCase\", \"es\": \"Dividir CamelCase\", \"pl\": \"Zawijaj CamelCase\", \"uk\": \"\u041F\u0435\u0440\u0435\u043D\u043E\u0441\u0438\u0442\u0438 CamelCase\", \"zh-cn\": \"CamelCase \u6362\u884C\" },\n \"buttonbkcolor\": { \"en\": \"Button background color\", \"de\": \"Schaltfl\u00E4chen-Hintergrundfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Cor de fundo do bot\u00E3o\", \"nl\": \"Achtergrondkleur knop\", \"fr\": \"Couleur d'arri\u00E8re-plan du bouton\", \"it\": \"Colore di sfondo del pulsante\", \"es\": \"Color de fondo del bot\u00F3n\", \"pl\": \"Kolor t\u0142a przycisku\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0444\u043E\u043D\u0443 \u043A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\u80CC\u666F\u989C\u8272\" },\n \"widgetPlayer\": { \"en\": \"Player widget\", \"de\": \"Player-Widget\", \"ru\": \"\u0412\u0438\u0434\u0436\u0435\u0442 \u043F\u0440\u043E\u0438\u0433\u0440\u044B\u0432\u0430\u0442\u0435\u043B\u044F\", \"pt\": \"Widget do leitor\", \"nl\": \"Spelerwidget\", \"fr\": \"Widget du lecteur\", \"it\": \"Widget del lettore\", \"es\": \"Widget del reproductor\", \"pl\": \"Wid\u017Cet odtwarzacza\", \"uk\": \"\u0412\u0456\u0434\u0436\u0435\u0442 \u043F\u0440\u043E\u0433\u0440\u0430\u0432\u0430\u0447\u0430\", \"zh-cn\": \"\u64AD\u653E\u5668\u5C0F\u90E8\u4EF6\" },\n \"widgetFavorites\": { \"en\": \"Favorite widget\", \"de\": \"Favoriten-Widget\", \"ru\": \"\u0412\u0438\u0434\u0436\u0435\u0442 \u0438\u0437\u0431\u0440\u0430\u043D\u043D\u043E\u0433\u043E\", \"pt\": \"Widget de favoritos\", \"nl\": \"Favorietenwidget\", \"fr\": \"Widget des favoris\", \"it\": \"Widget dei preferiti\", \"es\": \"Widget de favoritos\", \"pl\": \"Wid\u017Cet ulubionych\", \"uk\": \"\u0412\u0456\u0434\u0436\u0435\u0442 \u043E\u0431\u0440\u0430\u043D\u043E\u0433\u043E\", \"zh-cn\": \"\u6536\u85CF\u5939\u5C0F\u90E8\u4EF6\" },\n \"picHeight\": { \"en\": \"Button height\", \"de\": \"Schaltfl\u00E4chenh\u00F6he\", \"ru\": \"\u0412\u044B\u0441\u043E\u0442\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Altura do bot\u00E3o\", \"nl\": \"Knophoogte\", \"fr\": \"Hauteur du bouton\", \"it\": \"Altezza del pulsante\", \"es\": \"Altura del bot\u00F3n\", \"pl\": \"Wysoko\u015B\u0107 przycisku\", \"uk\": \"\u0412\u0438\u0441\u043E\u0442\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\u9AD8\u5EA6\" },\n \"picWidth\": { \"en\": \"Button width\", \"de\": \"Schaltfl\u00E4chenbreite\", \"ru\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Largura do bot\u00E3o\", \"nl\": \"Knopbreedte\", \"fr\": \"Largeur du bouton\", \"it\": \"Larghezza del pulsante\", \"es\": \"Anchura del bot\u00F3n\", \"pl\": \"Szeroko\u015B\u0107 przycisku\", \"uk\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\u5BBD\u5EA6\" },\n \"opacity\": { \"en\": \"Opacity\", \"de\": \"Deckkraft\", \"ru\": \"\u041D\u0435\u043F\u0440\u043E\u0437\u0440\u0430\u0447\u043D\u043E\u0441\u0442\u044C\", \"pt\": \"Opacidade\", \"nl\": \"Dekking\", \"fr\": \"Opacit\u00E9\", \"it\": \"Opacit\u00E0\", \"es\": \"Opacidad\", \"pl\": \"Krycie\", \"uk\": \"\u041D\u0435\u043F\u0440\u043E\u0437\u043E\u0440\u0456\u0441\u0442\u044C\", \"zh-cn\": \"\u4E0D\u900F\u660E\u5EA6\" },\n \"editmodehelper\": { \"en\": \"Edit Mode Helper\", \"de\": \"Bearbeitungsmodus-Hilfe\", \"ru\": \"\u041F\u043E\u043C\u043E\u0449\u043D\u0438\u043A \u0440\u0435\u0436\u0438\u043C\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\", \"pt\": \"Auxiliar do modo de edi\u00E7\u00E3o\", \"nl\": \"Hulp voor bewerkingsmodus\", \"fr\": \"Assistant du mode \u00E9dition\", \"it\": \"Assistente modalit\u00E0 modifica\", \"es\": \"Ayuda del modo de edici\u00F3n\", \"pl\": \"Pomoc trybu edycji\", \"uk\": \"\u041F\u043E\u043C\u0456\u0447\u043D\u0438\u043A \u0440\u0435\u0436\u0438\u043C\u0443 \u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043D\u043D\u044F\", \"zh-cn\": \"\u7F16\u8F91\u6A21\u5F0F\u52A9\u624B\" },\n \"group_buttonsettings\": { \"en\": \"Button options\", \"de\": \"Schaltfl\u00E4chenoptionen\", \"ru\": \"\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043A\u043D\u043E\u043F\u043E\u043A\", \"pt\": \"Op\u00E7\u00F5es dos bot\u00F5es\", \"nl\": \"Knopopties\", \"fr\": \"Options des boutons\", \"it\": \"Opzioni dei pulsanti\", \"es\": \"Opciones de botones\", \"pl\": \"Opcje przycisk\u00F3w\", \"uk\": \"\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0438 \u043A\u043D\u043E\u043F\u043E\u043A\", \"zh-cn\": \"\u6309\u94AE\u9009\u9879\" },\n \"borderwidth\": { \"en\": \"Border width\", \"de\": \"Rahmenbreite\", \"ru\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Largura da borda\", \"nl\": \"Randbreedte\", \"fr\": \"Largeur de bordure\", \"it\": \"Larghezza bordo\", \"es\": \"Anchura del borde\", \"pl\": \"Szeroko\u015B\u0107 obramowania\", \"uk\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u5BBD\u5EA6\" },\n \"borderstyle\": { \"en\": \"Border-style\", \"de\": \"Rahmenart\", \"ru\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Estilo da borda\", \"nl\": \"Randstijl\", \"fr\": \"Style de bordure\", \"it\": \"Stile bordo\", \"es\": \"Estilo del borde\", \"pl\": \"Styl obramowania\", \"uk\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u6837\u5F0F\" },\n \"bordercolornormal\": { \"en\": \"Border width normal\", \"de\": \"Rahmenfarbe normal\", \"ru\": \"\u041E\u0431\u044B\u0447\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor normal da borda\", \"nl\": \"Normale randkleur\", \"fr\": \"Couleur de bordure normale\", \"it\": \"Colore bordo normale\", \"es\": \"Color normal del borde\", \"pl\": \"Normalny kolor obramowania\", \"uk\": \"\u0417\u0432\u0438\u0447\u0430\u0439\u043D\u0438\u0439 \u043A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u666E\u901A\u8FB9\u6846\u989C\u8272\" },\n \"bordercoloractive\": { \"en\": \"Border width aktiv\", \"de\": \"Rahmenfarbe aktiv\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0439 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor da borda ativa\", \"nl\": \"Actieve randkleur\", \"fr\": \"Couleur de bordure active\", \"it\": \"Colore bordo attivo\", \"es\": \"Color del borde activo\", \"pl\": \"Kolor aktywnego obramowania\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0457 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u6D3B\u52A8\u8FB9\u6846\u989C\u8272\" },\n \"borderradius\": { \"en\": \"border-radius\", \"de\": \"Rahmenradius\", \"ru\": \"\u0420\u0430\u0434\u0438\u0443\u0441 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Raio da borda\", \"nl\": \"Randradius\", \"fr\": \"Rayon de bordure\", \"it\": \"Raggio bordo\", \"es\": \"Radio del borde\", \"pl\": \"Promie\u0144 obramowania\", \"uk\": \"\u0420\u0430\u0434\u0456\u0443\u0441 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u5706\u89D2\" },\n \"imagefwd\": { \"en\": \"Picture\", \"de\": \"Bild\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435\", \"pt\": \"Imagem\", \"nl\": \"Afbeelding\", \"fr\": \"Image\", \"it\": \"Immagine\", \"es\": \"Imagen\", \"pl\": \"Obraz\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u56FE\u7247\" },\n \"group_svgsettings\": { \"en\": \"SVG Settings\", \"de\": \"SVG-Einstellungen\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 SVG\", \"pt\": \"Defini\u00E7\u00F5es SVG\", \"nl\": \"SVG-instellingen\", \"fr\": \"Param\u00E8tres SVG\", \"it\": \"Impostazioni SVG\", \"es\": \"Ajustes SVG\", \"pl\": \"Ustawienia SVG\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F SVG\", \"zh-cn\": \"SVG \u8BBE\u7F6E\" },\n \"fillcolor\": { \"en\": \"fillcolor\", \"de\": \"F\u00FCllfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"pt\": \"Cor de preenchimento\", \"nl\": \"Vulkleur\", \"fr\": \"Couleur de remplissage\", \"it\": \"Colore riempimento\", \"es\": \"Color de relleno\", \"pl\": \"Kolor wype\u0142nienia\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"zh-cn\": \"\u586B\u5145\u989C\u8272\" },\n \"strokecolor\": { \"en\": \"strokecolor\", \"de\": \"Konturfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u043A\u043E\u043D\u0442\u0443\u0440\u0430\", \"pt\": \"Cor do contorno\", \"nl\": \"Lijnkleur\", \"fr\": \"Couleur du contour\", \"it\": \"Colore contorno\", \"es\": \"Color del trazo\", \"pl\": \"Kolor obrysu\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u043A\u043E\u043D\u0442\u0443\u0440\u0443\", \"zh-cn\": \"\u63CF\u8FB9\u989C\u8272\" },\n \"strokewidth\": { \"en\": \"strokewidth\", \"de\": \"Konturbreite\", \"ru\": \"\u0422\u043E\u043B\u0449\u0438\u043D\u0430 \u043A\u043E\u043D\u0442\u0443\u0440\u0430\", \"pt\": \"Largura do contorno\", \"nl\": \"Lijndikte\", \"fr\": \"Largeur du contour\", \"it\": \"Spessore contorno\", \"es\": \"Grosor del trazo\", \"pl\": \"Szeroko\u015B\u0107 obrysu\", \"uk\": \"\u0422\u043E\u0432\u0449\u0438\u043D\u0430 \u043A\u043E\u043D\u0442\u0443\u0440\u0443\", \"zh-cn\": \"\u63CF\u8FB9\u5BBD\u5EA6\" },\n \"imagerew\": { \"en\": \"Picture\", \"de\": \"Bild\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435\", \"pt\": \"Imagem\", \"nl\": \"Afbeelding\", \"fr\": \"Image\", \"it\": \"Immagine\", \"es\": \"Imagen\", \"pl\": \"Obraz\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u56FE\u7247\" },\n \"imagepause\": { \"en\": \"Picture pause\", \"de\": \"Bild Pause\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0430\u0443\u0437\u044B\", \"pt\": \"Imagem de pausa\", \"nl\": \"Afbeelding pauze\", \"fr\": \"Image de pause\", \"it\": \"Immagine pausa\", \"es\": \"Imagen de pausa\", \"pl\": \"Obraz pauzy\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u0430\u0443\u0437\u0438\", \"zh-cn\": \"\u6682\u505C\u56FE\u7247\" },\n \"imageplay\": { \"en\": \"Picture play\", \"de\": \"Bild Wiedergabe\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0434\u0435\u043D\u0438\u044F\", \"pt\": \"Imagem de reprodu\u00E7\u00E3o\", \"nl\": \"Afbeelding afspelen\", \"fr\": \"Image de lecture\", \"it\": \"Immagine riproduzione\", \"es\": \"Imagen de reproducci\u00F3n\", \"pl\": \"Obraz odtwarzania\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0432\u0456\u0434\u0442\u0432\u043E\u0440\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u64AD\u653E\u56FE\u7247\" },\n \"imagestop\": { \"en\": \"Picture stop\", \"de\": \"Bild Stopp\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438\", \"pt\": \"Imagem de paragem\", \"nl\": \"Afbeelding stoppen\", \"fr\": \"Image d'arr\u00EAt\", \"it\": \"Immagine arresto\", \"es\": \"Imagen de parada\", \"pl\": \"Obraz zatrzymania\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0437\u0443\u043F\u0438\u043D\u043A\u0438\", \"zh-cn\": \"\u505C\u6B62\u56FE\u7247\" },\n \"calctype\": { \"en\": \"CalcType\", \"de\": \"Berechnungsart\", \"ru\": \"\u0422\u0438\u043F \u0440\u0430\u0441\u0447\u0451\u0442\u0430\", \"pt\": \"Tipo de c\u00E1lculo\", \"nl\": \"Berekeningstype\", \"fr\": \"Type de calcul\", \"it\": \"Tipo di calcolo\", \"es\": \"Tipo de c\u00E1lculo\", \"pl\": \"Typ obliczenia\", \"uk\": \"\u0422\u0438\u043F \u043E\u0431\u0447\u0438\u0441\u043B\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u8BA1\u7B97\u7C7B\u578B\" },\n \"segments\": { \"en\": \"Segments\", \"de\": \"Segmente\", \"ru\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u044B\", \"pt\": \"Segmentos\", \"nl\": \"Segmenten\", \"fr\": \"Segments\", \"it\": \"Segmenti\", \"es\": \"Segmentos\", \"pl\": \"Segmenty\", \"uk\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u0438\", \"zh-cn\": \"\u5206\u6BB5\" },\n \"fillcolornormal\": { \"en\": \"fillcolornormal\", \"de\": \"Normale F\u00FCllfarbe\", \"ru\": \"\u041E\u0431\u044B\u0447\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"pt\": \"Cor de preenchimento normal\", \"nl\": \"Normale vulkleur\", \"fr\": \"Couleur de remplissage normale\", \"it\": \"Colore riempimento normale\", \"es\": \"Color de relleno normal\", \"pl\": \"Normalny kolor wype\u0142nienia\", \"uk\": \"\u0417\u0432\u0438\u0447\u0430\u0439\u043D\u0438\u0439 \u043A\u043E\u043B\u0456\u0440 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"zh-cn\": \"\u666E\u901A\u586B\u5145\u989C\u8272\" },\n \"fillcoloractive\": { \"en\": \"fillcoloractive\", \"de\": \"Aktive F\u00FCllfarbe\", \"ru\": \"\u0410\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"pt\": \"Cor de preenchimento ativa\", \"nl\": \"Actieve vulkleur\", \"fr\": \"Couleur de remplissage active\", \"it\": \"Colore riempimento attivo\", \"es\": \"Color de relleno activo\", \"pl\": \"Aktywny kolor wype\u0142nienia\", \"uk\": \"\u0410\u043A\u0442\u0438\u0432\u043D\u0438\u0439 \u043A\u043E\u043B\u0456\u0440 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"zh-cn\": \"\u6D3B\u52A8\u586B\u5145\u989C\u8272\" },\n \"position\": { \"en\": \"Format\", \"de\": \"Format\", \"ru\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"pt\": \"Formato\", \"nl\": \"Indeling\", \"fr\": \"Format\", \"it\": \"Formato\", \"es\": \"Formato\", \"pl\": \"Format\", \"uk\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"zh-cn\": \"\u683C\u5F0F\" },\n \"group_segmentsettings\": { \"en\": \"Segments\", \"de\": \"Segmente\", \"ru\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u044B\", \"pt\": \"Segmentos\", \"nl\": \"Segmenten\", \"fr\": \"Segments\", \"it\": \"Segmenti\", \"es\": \"Segmentos\", \"pl\": \"Segmenty\", \"uk\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u0438\", \"zh-cn\": \"\u5206\u6BB5\" },\n \"margin\": { \"en\": \"margin\", \"de\": \"Abstand\", \"ru\": \"\u041E\u0442\u0441\u0442\u0443\u043F\", \"pt\": \"Margem\", \"nl\": \"Marge\", \"fr\": \"Marge\", \"it\": \"Margine\", \"es\": \"Margen\", \"pl\": \"Margines\", \"uk\": \"\u0412\u0456\u0434\u0441\u0442\u0443\u043F\", \"zh-cn\": \"\u5916\u8FB9\u8DDD\" },\n \"imagerepeat0\": { \"en\": \"Picture without\", \"de\": \"Bild ohne Wiederholung\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0431\u0435\u0437 \u043F\u043E\u0432\u0442\u043E\u0440\u0430\", \"pt\": \"Imagem sem repeti\u00E7\u00E3o\", \"nl\": \"Afbeelding zonder herhaling\", \"fr\": \"Image sans r\u00E9p\u00E9tition\", \"it\": \"Immagine senza ripetizione\", \"es\": \"Imagen sin repetici\u00F3n\", \"pl\": \"Obraz bez powtarzania\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0431\u0435\u0437 \u043F\u043E\u0432\u0442\u043E\u0440\u0443\", \"zh-cn\": \"\u4E0D\u91CD\u590D\u56FE\u7247\" },\n \"imagerepeat1\": { \"en\": \"Picture Title\", \"de\": \"Bild Titel wiederholen\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u0430 \u0442\u0440\u0435\u043A\u0430\", \"pt\": \"Imagem de repeti\u00E7\u00E3o da faixa\", \"nl\": \"Afbeelding titel herhalen\", \"fr\": \"Image de r\u00E9p\u00E9tition du titre\", \"it\": \"Immagine ripeti titolo\", \"es\": \"Imagen de repetir t\u00EDtulo\", \"pl\": \"Obraz powtarzania utworu\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0443 \u0442\u0440\u0435\u043A\u0443\", \"zh-cn\": \"\u91CD\u590D\u66F2\u76EE\u56FE\u7247\" },\n \"imagerepeat2\": { \"en\": \"Picture Playlist\", \"de\": \"Bild Playlist wiederholen\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u0430 \u043F\u043B\u0435\u0439\u043B\u0438\u0441\u0442\u0430\", \"pt\": \"Imagem de repeti\u00E7\u00E3o da lista\", \"nl\": \"Afbeelding afspeellijst herhalen\", \"fr\": \"Image de r\u00E9p\u00E9tition de la playlist\", \"it\": \"Immagine ripeti playlist\", \"es\": \"Imagen de repetir lista\", \"pl\": \"Obraz powtarzania playlisty\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0443 \u0441\u043F\u0438\u0441\u043A\u0443\", \"zh-cn\": \"\u91CD\u590D\u64AD\u653E\u5217\u8868\u56FE\u7247\" },\n \"imageshuffle0\": { \"en\": \"Picture without\", \"de\": \"Bild ohne Zufallswiedergabe\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u043C\u0435\u0448\u0438\u0432\u0430\u043D\u0438\u044F\", \"pt\": \"Imagem sem reprodu\u00E7\u00E3o aleat\u00F3ria\", \"nl\": \"Afbeelding zonder willekeurig afspelen\", \"fr\": \"Image sans lecture al\u00E9atoire\", \"it\": \"Immagine senza riproduzione casuale\", \"es\": \"Imagen sin reproducci\u00F3n aleatoria\", \"pl\": \"Obraz bez odtwarzania losowego\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u043C\u0456\u0448\u0443\u0432\u0430\u043D\u043D\u044F\", \"zh-cn\": \"\u4E0D\u968F\u673A\u64AD\u653E\u56FE\u7247\" },\n \"imageshuffle1\": { \"en\": \"Picture Title\", \"de\": \"Bild Titel zuf\u00E4llig\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u0448\u0438\u0432\u0430\u043D\u0438\u044F \u0442\u0440\u0435\u043A\u043E\u0432\", \"pt\": \"Imagem de faixas aleat\u00F3rias\", \"nl\": \"Afbeelding titels willekeurig\", \"fr\": \"Image des titres al\u00E9atoires\", \"it\": \"Immagine titoli casuali\", \"es\": \"Imagen de t\u00EDtulos aleatorios\", \"pl\": \"Obraz losowania utwor\u00F3w\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043C\u0456\u0448\u0443\u0432\u0430\u043D\u043D\u044F \u0442\u0440\u0435\u043A\u0456\u0432\", \"zh-cn\": \"\u968F\u673A\u66F2\u76EE\u56FE\u7247\" },\n \"imageshuffle2\": { \"en\": \"Picture Album\", \"de\": \"Bild Album zuf\u00E4llig\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u0448\u0438\u0432\u0430\u043D\u0438\u044F \u0430\u043B\u044C\u0431\u043E\u043C\u043E\u0432\", \"pt\": \"Imagem de \u00E1lbuns aleat\u00F3rios\", \"nl\": \"Afbeelding albums willekeurig\", \"fr\": \"Image des albums al\u00E9atoires\", \"it\": \"Immagine album casuali\", \"es\": \"Imagen de \u00E1lbumes aleatorios\", \"pl\": \"Obraz losowania album\u00F3w\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043C\u0456\u0448\u0443\u0432\u0430\u043D\u043D\u044F \u0430\u043B\u044C\u0431\u043E\u043C\u0456\u0432\", \"zh-cn\": \"\u968F\u673A\u4E13\u8F91\u56FE\u7247\" },\n \"bordercolornogroup\": { \"en\": \"Border color - No group\", \"de\": \"Rahmenfarbe \u2013 Keine Gruppe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0431\u0435\u0437 \u0433\u0440\u0443\u043F\u043F\u044B\", \"pt\": \"Cor da borda \u2014 sem grupo\", \"nl\": \"Randkleur \u2014 geen groep\", \"fr\": \"Couleur de bordure \u2014 aucun groupe\", \"it\": \"Colore bordo \u2014 nessun gruppo\", \"es\": \"Color del borde \u2014 sin grupo\", \"pl\": \"Kolor obramowania \u2014 brak grupy\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0431\u0435\u0437 \u0433\u0440\u0443\u043F\u0438\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272 \u2014 \u65E0\u7EC4\" },\n \"bordercolorowngroup\": { \"en\": \"Border color - Own group\", \"de\": \"Rahmenfarbe \u2013 Eigene Gruppe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0441\u0432\u043E\u044F \u0433\u0440\u0443\u043F\u043F\u0430\", \"pt\": \"Cor da borda \u2014 grupo pr\u00F3prio\", \"nl\": \"Randkleur \u2014 eigen groep\", \"fr\": \"Couleur de bordure \u2014 groupe propre\", \"it\": \"Colore bordo \u2014 gruppo proprio\", \"es\": \"Color del borde \u2014 grupo propio\", \"pl\": \"Kolor obramowania \u2014 w\u0142asna grupa\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0432\u043B\u0430\u0441\u043D\u0430 \u0433\u0440\u0443\u043F\u0430\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272 \u2014 \u81EA\u5DF1\u7684\u7EC4\" },\n \"bordercolorothergroup\": { \"en\": \"Border color - Other group\", \"de\": \"Rahmenfarbe \u2013 Andere Gruppe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0434\u0440\u0443\u0433\u0430\u044F \u0433\u0440\u0443\u043F\u043F\u0430\", \"pt\": \"Cor da borda \u2014 outro grupo\", \"nl\": \"Randkleur \u2014 andere groep\", \"fr\": \"Couleur de bordure \u2014 autre groupe\", \"it\": \"Colore bordo \u2014 altro gruppo\", \"es\": \"Color del borde \u2014 otro grupo\", \"pl\": \"Kolor obramowania \u2014 inna grupa\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0456\u043D\u0448\u0430 \u0433\u0440\u0443\u043F\u0430\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272 \u2014 \u5176\u4ED6\u7EC4\" },\n \"group_rowsettings\": { \"en\": \"Row settings\", \"de\": \"Zeilenkonfiguration\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0441\u0442\u0440\u043E\u043A\u0438\", \"pt\": \"Defini\u00E7\u00F5es da linha\", \"nl\": \"Rij-instellingen\", \"fr\": \"Param\u00E8tres de ligne\", \"it\": \"Impostazioni riga\", \"es\": \"Ajustes de fila\", \"pl\": \"Ustawienia wiersza\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0440\u044F\u0434\u043A\u0430\", \"zh-cn\": \"\u884C\u8BBE\u7F6E\" },\n \"rowBackground\": { \"en\": \"Row background color\", \"de\": \"Hintergrundfarbe einer Zeile\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430 \u0441\u0442\u0440\u043E\u043A\u0438\", \"pt\": \"Cor de fundo da linha\", \"nl\": \"Achtergrondkleur rij\", \"fr\": \"Couleur d'arri\u00E8re-plan de la ligne\", \"it\": \"Colore di sfondo della riga\", \"es\": \"Color de fondo de la fila\", \"pl\": \"Kolor t\u0142a wiersza\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0444\u043E\u043D\u0443 \u0440\u044F\u0434\u043A\u0430\", \"zh-cn\": \"\u884C\u80CC\u666F\u989C\u8272\" },\n \"activeRowBackground\": { \"en\": \"Active row background color\", \"de\": \"Hintergrundfarbe der aktiven Zeile\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0438\", \"pt\": \"Cor de fundo da linha ativa\", \"nl\": \"Achtergrondkleur actieve rij\", \"fr\": \"Couleur d'arri\u00E8re-plan de la ligne active\", \"it\": \"Colore di sfondo della riga attiva\", \"es\": \"Color de fondo de la fila activa\", \"pl\": \"Kolor t\u0142a aktywnego wiersza\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0444\u043E\u043D\u0443 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0433\u043E \u0440\u044F\u0434\u043A\u0430\", \"zh-cn\": \"\u6D3B\u52A8\u884C\u80CC\u666F\u989C\u8272\" },\n \"rowBorderColor\": { \"en\": \"Border color\", \"de\": \"Rahmenfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor da borda\", \"nl\": \"Randkleur\", \"fr\": \"Couleur de bordure\", \"it\": \"Colore bordo\", \"es\": \"Color del borde\", \"pl\": \"Kolor obramowania\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272\" },\n \"rowBorderWidth\": { \"en\": \"Border width\", \"de\": \"Rahmenbreite\", \"ru\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Largura da borda\", \"nl\": \"Randbreedte\", \"fr\": \"Largeur de bordure\", \"it\": \"Larghezza bordo\", \"es\": \"Anchura del borde\", \"pl\": \"Szeroko\u015B\u0107 obramowania\", \"uk\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u5BBD\u5EA6\" },\n \"rowBorderStyle\": { \"en\": \"Border style\", \"de\": \"Rahmenart\", \"ru\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Estilo da borda\", \"nl\": \"Randstijl\", \"fr\": \"Style de bordure\", \"it\": \"Stile bordo\", \"es\": \"Estilo del borde\", \"pl\": \"Styl obramowania\", \"uk\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u6837\u5F0F\" },\n \"rowSpacing\": { \"en\": \"Spacing to next track\", \"de\": \"Abstand zum n\u00E4chsten Titel\", \"ru\": \"\u0418\u043D\u0442\u0435\u0440\u0432\u0430\u043B \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u0442\u0440\u0435\u043A\u0430\", \"pt\": \"Espa\u00E7o at\u00E9 \u00E0 faixa seguinte\", \"nl\": \"Afstand tot volgende nummer\", \"fr\": \"Espacement jusqu'au titre suivant\", \"it\": \"Spaziatura dal brano successivo\", \"es\": \"Espacio hasta la pista siguiente\", \"pl\": \"Odst\u0119p do nast\u0119pnego utworu\", \"uk\": \"\u0412\u0456\u0434\u0441\u0442\u0443\u043F \u0434\u043E \u043D\u0430\u0441\u0442\u0443\u043F\u043D\u043E\u0433\u043E \u0442\u0440\u0435\u043A\u0443\", \"zh-cn\": \"\u4E0E\u4E0B\u4E00\u66F2\u76EE\u7684\u95F4\u8DDD\" },\n \"showThumbnail\": { \"en\": \"Show thumbnail\", \"de\": \"Thumbnail anzeigen\", \"ru\": \"\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043C\u0438\u043D\u0438\u0430\u0442\u044E\u0440\u0443\", \"pt\": \"Mostrar miniatura\", \"nl\": \"Miniatuur tonen\", \"fr\": \"Afficher la miniature\", \"it\": \"Mostra miniatura\", \"es\": \"Mostrar miniatura\", \"pl\": \"Poka\u017C miniatur\u0119\", \"uk\": \"\u041F\u043E\u043A\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043C\u0456\u043D\u0456\u0430\u0442\u044E\u0440\u0443\", \"zh-cn\": \"\u663E\u793A\u7F29\u7565\u56FE\" },\n \"showIndex\": { \"en\": \"Show track index\", \"de\": \"Titelindex anzeigen\", \"ru\": \"\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043D\u043E\u043C\u0435\u0440 \u0442\u0440\u0435\u043A\u0430\", \"pt\": \"Mostrar \u00EDndice da faixa\", \"nl\": \"Nummerindex tonen\", \"fr\": \"Afficher l'index du titre\", \"it\": \"Mostra indice del brano\", \"es\": \"Mostrar \u00EDndice de pista\", \"pl\": \"Poka\u017C indeks utworu\", \"uk\": \"\u041F\u043E\u043A\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043D\u043E\u043C\u0435\u0440 \u0442\u0440\u0435\u043A\u0443\", \"zh-cn\": \"\u663E\u793A\u66F2\u76EE\u7D22\u5F15\" },\n \"buttonmargin\": { \"en\": \"Button spacing\", \"de\": \"Abstand zwischen Schaltfl\u00E4chen\", \"ru\": \"\u0420\u0430\u0441\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u043C\u0435\u0436\u0434\u0443 \u043A\u043D\u043E\u043F\u043A\u0430\u043C\u0438\", \"pt\": \"Espa\u00E7amento entre bot\u00F5es\", \"nl\": \"Afstand tussen knoppen\", \"fr\": \"Espacement entre les boutons\", \"it\": \"Spaziatura tra i pulsanti\", \"es\": \"Espacio entre botones\", \"pl\": \"Odst\u0119p mi\u0119dzy przyciskami\", \"uk\": \"\u0412\u0456\u0434\u0441\u0442\u0430\u043D\u044C \u043C\u0456\u0436 \u043A\u043D\u043E\u043F\u043A\u0430\u043C\u0438\", \"zh-cn\": \"\u6309\u94AE\u95F4\u8DDD\" },\n \"favoriteConfiguration\": { \"en\": \"Favorite configuration\", \"de\": \"Favoritenkonfiguration\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u0438\u0437\u0431\u0440\u0430\u043D\u043D\u043E\u0433\u043E\", \"pt\": \"Configura\u00E7\u00E3o de favoritos\", \"nl\": \"Favorietenconfiguratie\", \"fr\": \"Configuration des favoris\", \"it\": \"Configurazione dei preferiti\", \"es\": \"Configuraci\u00F3n de favoritos\", \"pl\": \"Konfiguracja ulubionych\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u0431\u0440\u0430\u043D\u043E\u0433\u043E\", \"zh-cn\": \"\u6536\u85CF\u914D\u7F6E\" },\n \"formatbutton\": { \"en\": \"Buttons\", \"de\": \"Schaltfl\u00E4chen\", \"ru\": \"\u041A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Bot\u00F5es\", \"nl\": \"Knoppen\", \"fr\": \"Boutons\", \"it\": \"Pulsanti\", \"es\": \"Botones\", \"pl\": \"Przyciski\", \"uk\": \"\u041A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\" },\n \"formatselect\": { \"en\": \"Selection list\", \"de\": \"Auswahlliste\", \"ru\": \"\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u044B\u0431\u043E\u0440\u0430\", \"pt\": \"Lista de sele\u00E7\u00E3o\", \"nl\": \"Keuzelijst\", \"fr\": \"Liste de s\u00E9lection\", \"it\": \"Elenco di selezione\", \"es\": \"Lista de selecci\u00F3n\", \"pl\": \"Lista wyboru\", \"uk\": \"\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u0438\u0431\u043E\u0440\u0443\", \"zh-cn\": \"\u9009\u62E9\u5217\u8868\" },\n \"formattype\": { \"en\": \"Display format\", \"de\": \"Anzeigeformat\", \"ru\": \"\u0424\u043E\u0440\u043C\u0430\u0442 \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F\", \"pt\": \"Formato de exibi\u00E7\u00E3o\", \"nl\": \"Weergaveformaat\", \"fr\": \"Format d'affichage\", \"it\": \"Formato di visualizzazione\", \"es\": \"Formato de visualizaci\u00F3n\", \"pl\": \"Format wy\u015Bwietlania\", \"uk\": \"\u0424\u043E\u0440\u043C\u0430\u0442 \u0432\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u663E\u793A\u683C\u5F0F\" },\n \"playerConfiguration\": { \"en\": \"Player configuration\", \"de\": \"Playerkonfiguration\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043F\u0440\u043E\u0438\u0433\u0440\u044B\u0432\u0430\u0442\u0435\u043B\u0435\u0439\", \"pt\": \"Configura\u00E7\u00E3o dos leitores\", \"nl\": \"Spelerconfiguratie\", \"fr\": \"Configuration des lecteurs\", \"it\": \"Configurazione dei lettori\", \"es\": \"Configuraci\u00F3n de reproductores\", \"pl\": \"Konfiguracja odtwarzaczy\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0440\u043E\u0433\u0440\u0430\u0432\u0430\u0447\u0456\u0432\", \"zh-cn\": \"\u64AD\u653E\u5668\u914D\u7F6E\" },\n \"mainbarcolor\": { \"en\": \"Main bar color\", \"de\": \"Farbe der Hauptleiste\", \"ru\": \"\u0426\u0432\u0435\u0442 \u043E\u0441\u043D\u043E\u0432\u043D\u043E\u0439 \u043F\u043E\u043B\u043E\u0441\u044B\", \"pt\": \"Cor da barra principal\", \"nl\": \"Kleur van de hoofdbalk\", \"fr\": \"Couleur de la barre principale\", \"it\": \"Colore della barra principale\", \"es\": \"Color de la barra principal\", \"pl\": \"Kolor paska g\u0142\u00F3wnego\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u043E\u0441\u043D\u043E\u0432\u043D\u043E\u0457 \u0441\u043C\u0443\u0433\u0438\", \"zh-cn\": \"\u4E3B\u8FDB\u5EA6\u6761\u989C\u8272\" },\n \"playtimebarcolor\": { \"en\": \"Elapsed time bar color\", \"de\": \"Farbe der Laufzeitleiste\", \"ru\": \"\u0426\u0432\u0435\u0442 \u043F\u043E\u043B\u043E\u0441\u044B \u043F\u0440\u043E\u0448\u0435\u0434\u0448\u0435\u0433\u043E \u0432\u0440\u0435\u043C\u0435\u043D\u0438\", \"pt\": \"Cor da barra de tempo decorrido\", \"nl\": \"Kleur van de verstreken-tijdbalk\", \"fr\": \"Couleur de la barre du temps \u00E9coul\u00E9\", \"it\": \"Colore della barra del tempo trascorso\", \"es\": \"Color de la barra de tiempo transcurrido\", \"pl\": \"Kolor paska up\u0142ywu czasu\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0441\u043C\u0443\u0433\u0438 \u043C\u0438\u043D\u0443\u043B\u043E\u0433\u043E \u0447\u0430\u0441\u0443\", \"zh-cn\": \"\u5DF2\u64AD\u653E\u65F6\u95F4\u6761\u989C\u8272\" },\n \"bordercolor\": { \"en\": \"Border color\", \"de\": \"Rahmenfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor da borda\", \"nl\": \"Randkleur\", \"fr\": \"Couleur de bordure\", \"it\": \"Colore bordo\", \"es\": \"Color del borde\", \"pl\": \"Kolor obramowania\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272\" },\n \"playerattribute\": { \"en\": \"Player attribute\", \"de\": \"Player-Attribut\", \"ru\": \"\u0410\u0442\u0440\u0438\u0431\u0443\u0442 \u043F\u0440\u043E\u0438\u0433\u0440\u044B\u0432\u0430\u0442\u0435\u043B\u044F\", \"pt\": \"Atributo do leitor\", \"nl\": \"Spelerattribuut\", \"fr\": \"Attribut du lecteur\", \"it\": \"Attributo del lettore\", \"es\": \"Atributo del reproductor\", \"pl\": \"Atrybut odtwarzacza\", \"uk\": \"\u0410\u0442\u0440\u0438\u0431\u0443\u0442 \u043F\u0440\u043E\u0433\u0440\u0430\u0432\u0430\u0447\u0430\", \"zh-cn\": \"\u64AD\u653E\u5668\u5C5E\u6027\" },\n \"format\": { \"en\": \"Format\", \"de\": \"Format\", \"ru\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"pt\": \"Formato\", \"nl\": \"Indeling\", \"fr\": \"Format\", \"it\": \"Formato\", \"es\": \"Formato\", \"pl\": \"Format\", \"uk\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"zh-cn\": \"\u683C\u5F0F\" },\n \"debug\": { \"en\": \"Debug\", \"de\": \"Debug-Ausgaben\", \"ru\": \"\u041E\u0442\u043B\u0430\u0434\u043A\u0430\", \"pt\": \"Depura\u00E7\u00E3o\", \"nl\": \"Foutopsporing\", \"fr\": \"D\u00E9bogage\", \"it\": \"Debug\", \"es\": \"Depuraci\u00F3n\", \"pl\": \"Debugowanie\", \"uk\": \"\u041D\u0430\u043B\u0430\u0433\u043E\u0434\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u8C03\u8BD5\" },\n \"debugwithFetchResults\": { \"en\": \"Debug with fetched results\", \"de\": \"Debug-Ausgaben mit abgerufenen Ergebnissen\", \"ru\": \"\u041E\u0442\u043B\u0430\u0434\u043A\u0430 \u0441 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043D\u044B\u043C\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0430\u043C\u0438\", \"pt\": \"Depura\u00E7\u00E3o com resultados obtidos\", \"nl\": \"Foutopsporing met opgehaalde resultaten\", \"fr\": \"D\u00E9bogage avec les r\u00E9sultats r\u00E9cup\u00E9r\u00E9s\", \"it\": \"Debug con i risultati recuperati\", \"es\": \"Depuraci\u00F3n con los resultados obtenidos\", \"pl\": \"Debugowanie z pobranymi wynikami\", \"uk\": \"\u041D\u0430\u043B\u0430\u0433\u043E\u0434\u0436\u0435\u043D\u043D\u044F \u0437 \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u0438\u043C\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0430\u043C\u0438\", \"zh-cn\": \"\u8C03\u8BD5\u5E76\u8F93\u51FA\u83B7\u53D6\u7ED3\u679C\" }\n}\n", "/* xeslint no-extend-native: 0 */\n/* globals navigator */\n(function () {\n // Defining locale\n Date.shortMonths = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n Date.longMonths = [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"];\n Date.shortDays = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n Date.longDays = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\n // Defining patterns\n const replaceChars = {\n // Day\n d: function () { const d = this.getDate(); return (d < 10 ? \"0\" : \"\") + d; },\n D: function () { return Date.shortDays[this.getDay()]; },\n j: function () { return this.getDate(); },\n l: function () { return Date.longDays[this.getDay()]; },\n N: function () { const N = this.getDay(); return (N === 0 ? 7 : N); },\n S: function () { const S = this.getDate(); return (S % 10 === 1 && S !== 11 ? \"st\" : (S % 10 === 2 && S !== 12 ? \"nd\" : (S % 10 === 3 && S !== 13 ? \"rd\" : \"th\"))); },\n w: function () { return this.getDay(); },\n z: function () { const d = new Date(this.getFullYear(), 0, 1); return Math.ceil((this - d) / 86400000); },\n // Week\n W: function () {\n const target = new Date(this.valueOf());\n const dayNr = (this.getDay() + 6) % 7;\n target.setDate(target.getDate() - dayNr + 3);\n const firstThursday = target.valueOf();\n target.setMonth(0, 1);\n if (target.getDay() !== 4) {\n target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);\n }\n const retVal = 1 + Math.ceil((firstThursday - target) / 604800000);\n\n return (retVal < 10 ? \"0\" + retVal : retVal);\n },\n // Month\n F: function () { return Date.longMonths[this.getMonth()]; },\n m: function () { const m = this.getMonth(); return (m < 9 ? \"0\" : \"\") + (m + 1); },\n M: function () { return Date.shortMonths[this.getMonth()]; },\n n: function () { return this.getMonth() + 1; },\n t: function () {\n let year = this.getFullYear();\n let nextMonth = this.getMonth() + 1;\n if (nextMonth === 12) {\n year = year++;\n nextMonth = 0;\n }\n return new Date(year, nextMonth, 0).getDate();\n },\n // Year\n L: function () { const L = this.getFullYear(); return (L % 400 === 0 || (L % 100 !== 0 && L % 4 === 0)); },\n o: function () { const d = new Date(this.valueOf()); d.setDate(d.getDate() - ((this.getDay() + 6) % 7) + 3); return d.getFullYear(); },\n Y: function () { return this.getFullYear(); },\n y: function () { return (\"\" + this.getFullYear()).substr(2); },\n // Time\n a: function () { return this.getHours() < 12 ? \"am\" : \"pm\"; },\n A: function () { return this.getHours() < 12 ? \"AM\" : \"PM\"; },\n B: function () { return Math.floor((((this.getUTCHours() + 1) % 24) + this.getUTCMinutes() / 60 + this.getUTCSeconds() / 3600) * 1000 / 24); },\n g: function () { return this.getHours() % 12 || 12; },\n G: function () { return this.getHours(); },\n h: function () { const h = this.getHours(); return ((h % 12 || 12) < 10 ? \"0\" : \"\") + (h % 12 || 12); },\n H: function () { const H = this.getHours(); return (H < 10 ? \"0\" : \"\") + H; },\n i: function () { const i = this.getMinutes(); return (i < 10 ? \"0\" : \"\") + i; },\n s: function () { const s = this.getSeconds(); return (s < 10 ? \"0\" : \"\") + s; },\n v: function () { const v = this.getMilliseconds(); return (v < 10 ? \"00\" : (v < 100 ? \"0\" : \"\")) + v; },\n // Timezone\n e: function () { return Intl.DateTimeFormat().resolvedOptions().timeZone; },\n I: function () {\n let DST = null;\n for (let i = 0; i < 12; ++i) {\n const d = new Date(this.getFullYear(), i, 1);\n const offset = d.getTimezoneOffset();\n\n if (DST === null) DST = offset;\n else if (offset < DST) { DST = offset; break; } else if (offset > DST) break;\n }\n return (this.getTimezoneOffset() === DST) | 0;\n },\n O: function () { const O = this.getTimezoneOffset(); return (-O < 0 ? \"-\" : \"+\") + (Math.abs(O / 60) < 10 ? \"0\" : \"\") + Math.floor(Math.abs(O / 60)) + (Math.abs(O % 60) === 0 ? \"00\" : ((Math.abs(O % 60) < 10 ? \"0\" : \"\")) + (Math.abs(O % 60))); },\n P: function () { const P = this.getTimezoneOffset(); return (-P < 0 ? \"-\" : \"+\") + (Math.abs(P / 60) < 10 ? \"0\" : \"\") + Math.floor(Math.abs(P / 60)) + \":\" + (Math.abs(P % 60) === 0 ? \"00\" : ((Math.abs(P % 60) < 10 ? \"0\" : \"\")) + (Math.abs(P % 60))); },\n T: function () { const tz = this.toLocaleTimeString(navigator.language, { timeZoneName: \"short\" }).split(\" \"); return tz[tz.length - 1]; },\n Z: function () { return -this.getTimezoneOffset() * 60; },\n // Full Date/Time\n c: function () { return this.format(\"Y-m-d\\\\TH:i:sP\"); },\n r: function () { return this.toString(); },\n U: function () { return Math.floor(this.getTime() / 1000); }\n };\n\n // Simulates PHP's date function\n Date.prototype.format = function (format) {\n const date = this;\n return format.replace(/(\\\\?)(.)/g, function (_, esc, chr) {\n return (esc === \"\" && replaceChars[chr]) ? replaceChars[chr].call(date) : chr;\n });\n };\n}).call(this);", "'use strict';\n\n/**\n * This function takes a request and returns an appropriate class that can parse the response.\n * The class is determined by the content of the response.\n *\n * @param request - The request object.\n * @returns The class that can parse the response.\n */\nexport function parseRequestFactory(request) {\n console.log(`parseRequestFactory`);\n let result = request.result;\n if (result.albums_loop) {\n return new Albums(request);\n }\n if (result.artists_loop) {\n return new Artists(request);\n }\n if (result.genres_loop) {\n return new Genres(request);\n }\n if (result.works_loop) {\n return new Works(request);\n }\n if (result.years_loop) {\n return new Years(request);\n }\n if (result.item_loop) {\n return new Items(request);\n }\n if (result.titles_loop) {\n return new Tracks(request);\n }\n if (result.playlisttracks_loop) {\n return new PlaylistTracks(request);\n }\n if (result.playlists_loop) {\n return new Playlists(request);\n }\n //specialHandling\n let requestCommand = request.params[1][0];\n if (requestCommand === 'selectVirtualLibrary' && !result.item_loop) {\n return new Items(request);\n }\n}\nclass Albums {\n constructor(request) {\n console.log(`Albums`);\n this.albums = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.albums_loop) {\n let albums = result.albums_loop;\n return albums.map(item => {\n return new Album(item, request);\n });\n }\n }\n getMenuItems() {\n return this.albums.map(item => item.getMenu());\n }\n}\nclass Album {\n constructor(request_item, request) {\n this.parseRequest(request_item, request);\n }\n parseRequest(request_item, request) {\n this.id = request_item.id || undefined;\n this.performance = request_item.performance || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.favorites_title = request_item.favorites_title || undefined;\n this.album = request_item.album || undefined;\n this.year = request_item.year || undefined;\n this.artwork_track_id = request_item.artwork_track_id || undefined;\n this.compilation = request_item.compilation || undefined;\n this.artist_id = request_item.artist_id || undefined;\n this.artist = request_item.artist || undefined;\n this.textkey = request_item.textkey || undefined;\n let additionalPlayParams = [getParamsFromCommand(request.params[1], 'role_id:')];\n this.actions = {\n next: {\n command: ['tracks'],\n params: ['tags:distbhz1kyuAACGPSE', 'sort:tracknum', `album_id:${this.id}`],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `album_id:${this.id}`, `performance:`, ...additionalPlayParams, `library_id:-1`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `album_id:${this.id}`, `performance:`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: `${this.artist} / ${this.album} ${this.year ? `(${this.year})` : ''}`,\n image: `/music/${this.artwork_track_id}/cover_300x300_f`,\n type: 'album',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass Artists {\n constructor(request) {\n console.log(`Artists`);\n this.artists = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.artists_loop) {\n let artists = result.artists_loop;\n return artists.map(item => {\n return new Artist(item, request);\n });\n }\n }\n getMenuItems() {\n return this.artists.map(item => item.getMenu());\n }\n}\nclass Artist {\n constructor(request_item, request) {\n this.parseRequest(request_item, request);\n }\n parseRequest(request_item, request) {\n this.id = request_item.id || undefined;\n this.artist = request_item.artist || undefined;\n this.textkey = request_item.textkey || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n let additionalPlayParams = [getParamsFromCommand(request.params[1], 'role_id:')];\n this.actions = {\n next: {\n command: ['albums'],\n params: ['tags:aajlqswyKSSE', 'sort:yearalbum', `artist_id:${this.id}`],\n },\n play: {\n command: ['playlistcontrol'],\n params: [\n `cmd:load`,\n `role_id:ALBUMARTIST`,\n `artist_id:${this.id}`,\n `sort:yearalbum`,\n ...additionalPlayParams,\n `library_id:-1`,\n ],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `role_id:ALBUMARTIST`, `artist_id:${this.id}`, `sort:yearalbum`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: this.artist,\n image: `/imageproxy/mai/artist/${this.id}/image_300x300_f`,\n type: 'artist',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass Genres {\n constructor(request) {\n console.log(`Genres`);\n this.genres = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.genres_loop) {\n let genres = result.genres_loop;\n return genres.map(item => {\n return new Genre(item);\n });\n }\n }\n getMenuItems() {\n return this.genres.map(item => item.getMenu());\n }\n}\nclass Genre {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.genre = request_item.genre || undefined;\n this.textkey = request_item.textkey || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.actions = {\n next: {\n command: ['tracks'],\n params: [`genre_id:${request_item.id}`, 'tags:distbhz1kyuAACGPScelyE', 'msk-sort:yearalbumtrack:Album'],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `genre_id:${this.id}`, `sort:album`, `library_id:-1`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `genre_id:${this.id}`, `sort:album`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: `${this.genre}`,\n image: null,\n type: 'genre',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass Playlists {\n constructor(request) {\n console.log(`Playlists`);\n this.playlists = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.playlists_loop) {\n let playlists = result.playlists_loop;\n return playlists.map(item => {\n return new Playlist(item);\n });\n }\n }\n getMenuItems() {\n return this.playlists.map(item => item.getMenu());\n }\n}\nclass Playlist {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.playlist = request_item.playlist || undefined;\n this.url = request_item.url || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.textkey = request_item.textkey || undefined;\n this.extid = request_item.extid || undefined;\n this.remote = request_item.remote || undefined;\n this.actions = {\n next: {\n command: ['playlists', 'tracks'],\n params: [`playlist_id:${request_item.id}`, 'tags:distbhz1acelyAGKPS'],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `playlist_id:${this.id}`, `performance:`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `playlist_id:${this.id}`, `performance:`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: `${this.playlist}`,\n image: null,\n type: 'playlist',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass Works {\n constructor(request) {\n console.log(`Works`);\n this.works = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.works_loop) {\n let works = result.works_loop;\n return works.map(item => {\n return new Work(item);\n });\n }\n }\n getMenuItems() {\n return this.works.map(item => item.getMenu());\n }\n}\nclass Work {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.work_id || undefined;\n this.composer = request_item.composer || undefined;\n this.work = request_item.work || undefined;\n this.composer_id = request_item.composer_id || undefined;\n this.album_id = request_item.album_id || undefined;\n this.textkey = request_item.textkey || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.favorites_title = request_item.favorites_title || undefined;\n this.actions = {\n next: {\n command: ['albums'],\n params: [\n 'tags:aajlqswyKSSE',\n `work_id:${this.id}`,\n `composer_id:${this.composer_id}`,\n `album_id:${this.album_id}`,\n ],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `work_id:${this.id}`, `album_id:${this.album_id}`, `performance:`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `work_id:${this.id}`, `album_id:${this.album_id}`, `performance:`],\n },\n };\n }\n getMenu() {\n return {\n id: `work_id:${this.id}`,\n title: `${this.favorites_title}`,\n image: null,\n type: 'work',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass Years {\n constructor(request) {\n console.log(`Years`);\n this.years = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.years_loop) {\n let years = result.years_loop;\n return years.map(item => {\n return new Year(item);\n });\n }\n }\n getMenuItems() {\n return this.years.map(item => item.getMenu());\n }\n}\nclass Year {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.year || undefined;\n this.year = request_item.year || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.actions = {\n next: {\n command: ['albums'],\n params: [\n 'release_type:Album',\n 'tags:aajlqswyKSSE',\n 'sort:album',\n 'menu:1',\n `year:${request_item.year}`,\n ],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `year:${this.id}`, `library_id:-1`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `year:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `year_id:${this.id}`,\n title: `${this.year}`,\n image: null,\n type: 'year',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass Tracks {\n constructor(request) {\n console.log(`Tracks`);\n this.tracks = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.titles_loop) {\n let tracks = result.titles_loop;\n return tracks.map(item => {\n return new Track(item);\n });\n }\n }\n getMenuItems() {\n return this.tracks.map(item => item.getMenu());\n }\n}\nclass Track {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.title = request_item.title || undefined;\n this.duration = request_item.duration || undefined;\n this.artist_id = request_item.artist_id || undefined;\n this.tracknum = request_item.tracknum || undefined;\n this.year = request_item.year || undefined;\n this.albumartist = request_item.albumartist || undefined;\n this.trackartist = request_item.trackartist || undefined;\n this.compilation = request_item.compilation || undefined;\n this.genres = request_item.genres || undefined;\n this.genre_ids = request_item.genre_ids || undefined;\n this.albumartist_ids = request_item.albumartist_ids || undefined;\n this.trackartist_ids = request_item.trackartist_ids || undefined;\n this.actions = {\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `track_id:${this.id}`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `track_id:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `track_id:${this.id}`,\n title: `${this.title}`,\n image: null,\n type: 'track',\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass PlaylistTracks {\n constructor(request) {\n console.log(`PlaylistTracks`);\n this.playlisttracks = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.playlisttracks_loop) {\n let playlisttracks = result.playlisttracks_loop;\n return playlisttracks.map(item => {\n return new PlaylistTrack(item);\n });\n }\n }\n getMenuItems() {\n return this.playlisttracks.map(item => item.getMenu());\n }\n}\nclass PlaylistTrack {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.title = request_item.title || undefined;\n this['playlist index'] = request_item['playlist index'] || undefined;\n this.title = request_item.title || undefined;\n this.duration = request_item.duration || undefined;\n this.artist_ids = request_item.artist_ids || undefined;\n this.tracknum = request_item.tracknum || undefined;\n this.artist = request_item.artist || undefined;\n this.coverid = request_item.coverid || undefined;\n this.album_id = request_item.album_id || undefined;\n this.album = request_item.album || undefined;\n this.year = request_item.year || undefined;\n this.genres = request_item.genres || undefined;\n this.genre_ids = request_item.genre_ids || undefined;\n this.artist_ids = request_item.artist_ids || undefined;\n this.actions = {\n next: {\n command: ['playlist', 'tracks'],\n params: ['tags:distbhz1acelyAGKPS', 'playlist_id:${this.id}'],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:load`, `folder_id:${this.id}`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:add`, `folder_id:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `track_id:${this.id}`,\n title: `${this.title}`,\n image: null,\n type: 'playlisttrack',\n item: this,\n };\n }\n}\nclass Items {\n constructor(request) {\n console.log(`Items`);\n let filesystem = request.params[1].includes('mode:filesystem');\n let requestCommand = request.params[1][0] + (filesystem ? 'FS' : '');\n this.items = this.parseRequest(request, requestCommand);\n }\n parseRequest(request, requestCommand) {\n let result = request.result;\n if (result.item_loop) {\n let items = result.item_loop;\n return items.map(item => {\n return Item.create(item, requestCommand, request);\n });\n }\n if (!result.titles_loop && requestCommand === 'selectVirtualLibrary') {\n return [\n Item.create(\n {\n type: 'virtualLibraryAnswer',\n text: request.result.title,\n },\n requestCommand,\n ),\n ];\n }\n }\n getMenuItems() {\n return this.items.map(item => item.getMenu());\n }\n}\nclass Item {\n // item types\n // search|text|textarea|audio|playlist|link|opml|replace|redirect|radio\n static create(request_item, requestCommand, request) {\n console.log(`Item switch: ${requestCommand}_${request_item.type || ''}`);\n switch (`${requestCommand}_${request_item.type || ''}`) {\n case 'radios_':\n case 'local_':\n case 'music_':\n case 'sports_':\n case 'news_':\n case 'talk_':\n case 'location_':\n case 'language_':\n case 'podcast_':\n case 'local_link':\n case 'music_link':\n case 'sports_link':\n case 'news_link':\n case 'talk_link':\n case 'location_link':\n case 'language_link':\n case 'podcast_link':\n return new ItemRadio(request_item, requestCommand);\n case 'local_text':\n case 'music_text':\n case 'sports_text':\n case 'news_text':\n case 'talk_text':\n case 'location_text':\n case 'language_text':\n case 'podcast_text':\n case 'browselibrary_text':\n case 'browselibraryFS_text':\n return new ItemText(request_item, requestCommand);\n case 'menu_':\n return new ItemMenu(request_item, request);\n case 'browselibrary_playlist':\n case 'favorites_playlist':\n return new ItemPlaylist(request_item, false);\n case 'browselibraryFS_playlist':\n return new ItemPlaylist(request_item, true);\n case 'browselibraryFS_':\n return new ItemFilesystem(request_item);\n case 'browselibrary_audio': //ok\n case 'browselibraryFS_audio': //ok\n case 'local_audio': //ok\n case 'music_audio': //ok\n case 'sports_audio': //ok\n case 'news_audio': //ok\n case 'talk_audio': //ok\n case 'location_audio': //ok\n case 'language_audio': //ok\n case 'podcast_audio': //ok\n case 'favorites_audio': //ok\n return new ItemAudio(request_item, requestCommand);\n case 'selectVirtualLibrary_virtualLibraryAnswer':\n return new ItemVirtualLibraryAnswer(request_item);\n case 'selectVirtualLibrary_':\n case 'selectVirtualLibrary_outline':\n return new ItemVirtualLibrary(request_item);\n case 'myapps_redirect':\n return new ItemApplication(request_item);\n default:\n return new ItemMenu(request_item, request);\n // debugger;\n // throw new Error(`Unknown item type: ${requestCommand}_${request_item.type || ''}`);\n }\n }\n}\nclass ItemApplication extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.actions.go.params.menu || undefined;\n this.text = request_item.text.trim() || undefined;\n this.iconid = request_item['icon-id'] || undefined;\n this.actions = {};\n if (request_item.actions['go']) {\n this.actions = {\n ...this.actions,\n ...{ next: translateMyMusicParameters(request_item.actions.go) },\n };\n }\n if (request_item.actions['play']) {\n this.actions = {\n ...this.actions,\n ...{ play: translateMyMusicParameters(request_item.actions.play) },\n };\n }\n if (request_item.actions['add']) {\n this.actions = {\n ...this.actions,\n ...{ add: translateMyMusicParameters(request_item.actions.add) },\n };\n }\n }\n getMenu() {\n return {\n id: this.id,\n title: this.text,\n image: this.icon,\n type: 'itemapplication',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemRadio extends Item {\n constructor(request_item, requestCommand) {\n super(request_item);\n this.parseRequest(request_item, requestCommand);\n }\n parseRequest(request_item, requestCommand) {\n let cmd;\n if (request_item.actions?.go) {\n cmd = translateMyMusicParameters(request_item.actions?.go);\n } else {\n cmd = {\n command: [requestCommand, 'items'],\n params: [`menu:${requestCommand}`, `item_id:${request_item.actions.go.params.item_id}`],\n };\n }\n this.id = request_item.actions.go.params.item_id || request_item.actions.go.params.menu || undefined;\n this.text = request_item.text || undefined;\n this.actions = {\n next: cmd,\n };\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'radiolocal',\n param: JSON.stringify(this.actions.next),\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemMenu extends Item {\n constructor(request_item, request) {\n super(request_item);\n this.parseRequest(request_item, request);\n }\n parseRequest(request_item, request) {\n this.id = request_item.text || undefined;\n this.text = request_item.text || 'Empty';\n this.node = request_item.node || undefined;\n this.weight = request_item.weight || undefined;\n if (request_item.actions) {\n if (request_item.actions['go']) {\n this.actions = {\n ...this.actions,\n ...{ next: translateMyMusicParameters(request_item.actions.go) },\n };\n }\n if (request_item.actions['play']) {\n this.actions = {\n ...this.actions,\n ...{ play: translateMyMusicParameters(request_item.actions.play) },\n };\n }\n if (request_item.actions['add']) {\n this.actions = {\n ...this.actions,\n ...{ add: translateMyMusicParameters(request_item.actions.add) },\n };\n }\n if (request_item.actions['do']) {\n this.actions = {\n ...this.actions,\n ...{ add: translateMyMusicParameters(request_item.actions.do) },\n };\n }\n }\n if (request_item.goAction) {\n if (request_item.goAction == 'play') {\n const filteredParams = Object.keys(request_item.params)\n .filter(key => !key.includes('touchToPlay'))\n .reduce((obj, key) => {\n obj[key] = request_item.params[key];\n return obj;\n }, {});\n this.actions = {\n play: {\n command: request.result.base.actions[request_item.goAction].cmd,\n params: [\n ...object2Array({\n ...request.result.base.actions[request_item.goAction].params,\n ...filteredParams,\n }),\n ],\n },\n };\n }\n }\n // if (request_item.actions) {\n // const priorityKeys = ['go', 'do'];\n // const goAction = priorityKeys.find(key => Object.prototype.hasOwnProperty.call(request_item.actions, key));\n // if (goAction) {\n // cmd = {\n // ...{ cmd: request_item.actions[goAction].cmd },\n // ...{ param: request_item.actions[goAction].param },\n // };\n // } else {\n // console.log('Please check: no valid action');\n // }\n\n // // cmd = {\n // // ...{ cmd: request.result.base.actions[goAction].cmd },\n // // ...{ param: request.result.base.actions[goAction].param },\n // // };\n // this.actions = {\n // next: cmd,\n // };\n // }\n }\n getMenu() {\n return {\n id: this.id,\n title: this.text,\n image: null,\n type: 'menu',\n actions: JSON.stringify(this.actions),\n item: this,\n };\n }\n}\nclass ItemFilesystem extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n let cmd;\n if (request_item.actions?.go) {\n cmd = translateMyMusicParameters(request_item.actions?.go);\n }\n\n this.id = request_item.actions?.go.params.item_id || undefined;\n this.text = request_item.text || undefined;\n this.actions = {\n next: cmd,\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: this.text,\n image: null,\n type: 'menu',\n param: JSON.stringify(this.actions.next),\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemPlaylist extends Item {\n constructor(request_item, filesystem) {\n super(request_item);\n this.parseRequest(request_item, filesystem);\n }\n parseRequest(request_item, filesystem) {\n this.id = request_item.actions?.more.params.folder_id || undefined;\n this.text = request_item.text || undefined;\n this.textkey = request_item.textkey || undefined;\n this.actions = {\n next: {\n command: ['browselibrary', 'items'],\n params: [\n 'menu:browselibrary',\n filesystem ? 'mode:filesystem' : 'mode:bmf',\n ...object2Array(request_item.params),\n ],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:load`, `folder_id:${this.id}`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:add`, `folder_id:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: `(D) ${this.text}`,\n image: null,\n type: 'itemplaylist',\n param: JSON.stringify(this.actions.next),\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemText extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.text || undefined;\n this.text = request_item.text || undefined;\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'itemtext',\n param: null,\n item: this,\n };\n }\n}\nclass ItemAudio extends Item {\n constructor(request_item, requestCommand) {\n super(request_item);\n this.parseRequest(request_item, requestCommand);\n }\n parseRequest(request_item, requestCommand) {\n this.id = request_item.commonParams?.track_id || request_item.params?.item_id || undefined;\n this.text = request_item.text || undefined;\n this.textkey = request_item.textkey || undefined;\n this.icon = request_item.icon || undefined;\n this.iconid = request_item['icon-id'] || undefined;\n this.favorites_type = request_item.presetParams.favorites_type || undefined;\n this.favorites_url = request_item.presetParams.favorites_url || undefined;\n this.favorites_title = request_item.presetParams.favorites_title || undefined;\n this.icon = request_item.presetParams.icon || undefined;\n this.actions = {\n play: {\n command: [...(requestCommand === 'browselibraryFS' ? ['browselibrary'] : [requestCommand])],\n params: [\n 'playlist',\n 'play',\n ...(requestCommand === 'browselibrary' ? ['mode:bmf'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['mode:filesystem'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['menu:browselibrary'] : [requestCommand]),\n `item_id:${this.id}`,\n `isContextMenu:1`,\n ],\n },\n add: {\n command: [...(requestCommand === 'browselibraryFS' ? ['browselibrary'] : [requestCommand])],\n params: [\n 'playlist',\n 'add',\n ...(requestCommand === 'browselibrary' ? ['mode:bmf'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['mode:filesystem'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['menu:browselibrary'] : [requestCommand]),\n `item_id:${this.id}`,\n `isContextMenu:1`,\n ],\n },\n };\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: `${this.text}`,\n image: this.icon,\n type: 'itemaudio',\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemVirtualLibrary extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.actions?.go.params.item_id || undefined;\n this.text = request_item.text || undefined;\n let cmd = {\n command: ['selectVirtualLibrary', 'items'],\n params: [`item_id:${request_item.actions.go.params.item_id}`, 'menu:selectVirtualLibrary'],\n };\n this.actions = {\n next: cmd,\n };\n\n /* \n {\n \"addAction\": \"go\",\n \"text\": \"All Library (Default)\",\n \"actions\": {\n \"go\": {\n \"cmd\": [\n \"selectVirtualLibrary\",\n \"items\"\n ],\n \"params\": {\n \"item_id\": \"0\",\n \"menu\": \"selectVirtualLibrary\"\n },\n \"nextWindow\": \"myMusic\"\n }\n }\n } */\n }\n\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'itemvirtuallibrary',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass ItemVirtualLibraryAnswer extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.actions?.go.params.item_id || undefined;\n this.text = request_item.text || undefined;\n }\n\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'itemvirtuallibraryanswer',\n item: this,\n param: null,\n };\n }\n}\nfunction object2Array(obj) {\n return Object.keys(obj).map(function (key) {\n return `${key}:${obj[key]}`;\n });\n}\nfunction getParamsFromCommand(params, key) {\n return params.find(item => item.toString().startsWith(key));\n}\nfunction translateMyMusicParameters(command /* , request */) {\n console.log(command);\n if (command.cmd == undefined) {\n return undefined;\n }\n var cmd = { command: [...command.cmd], params: [] };\n for (var key in command.params) {\n let p = command.params[key];\n if (p != undefined && p != null && p.length > 0) {\n cmd.params.push(`${key}:${p}`);\n }\n }\n\n let c = [];\n let p = [];\n var mode = undefined;\n var canReplace = true;\n var hasSort = false;\n var hasTags = false;\n var hasArtistId = false;\n var hasLibraryId = false;\n var hasNonArtistRole = false;\n for (let i = 0, params = cmd.params; i < cmd.params.length; i++) {\n if (params[i].startsWith('mode:')) {\n mode = params[i].split(':')[1];\n if (mode.startsWith('myMusicArtists')) {\n mode = 'artists';\n } else if (\n mode.startsWith('myMusicAlbums') ||\n mode == 'randomalbums' ||\n mode == 'vaalbums' ||\n mode == 'recentlychanged'\n ) {\n mode = 'albums';\n } else if (mode == 'years') {\n p.push('hasAlbums:1');\n } else if (mode.startsWith('myMusicWorks')) {\n mode = 'works';\n } else if (\n mode != 'artists' &&\n mode != 'albums' &&\n mode != 'genres' &&\n mode != 'tracks' &&\n mode != 'playlists' &&\n mode != 'works'\n ) {\n canReplace = false;\n break;\n }\n c.push(mode);\n }\n if (!params[i].startsWith('menu:')) {\n if (params[i].startsWith('tags:')) {\n if (params[i].split(':')[1].indexOf('s') < 0) {\n i += 's';\n }\n p.push(params[i]);\n hasTags = true;\n } else {\n p.push(params[i]);\n if (params[i].startsWith('sort:')) {\n hasSort = true;\n } else if (params[i].startsWith('artist_id:')) {\n hasArtistId = true;\n } else if (params[i].startsWith('library_id:')) {\n hasLibraryId = true;\n } else if (params[i].startsWith('role_id:')) {\n var role = params[i].split(':')[1].toLowerCase();\n if ('albumartist' != role && '5' != role) {\n hasNonArtistRole = true;\n }\n }\n }\n }\n }\n\n if (canReplace && c.length == 1 && mode) {\n if (mode == 'tracks') {\n if (!hasTags) {\n // If view.current.id starts with \"track_id:\" then we are in a 'More' menu, therefore\n // want cover id of tracks...\n // tags:distbhz1kyuAACGPSc\n p.push('tags:distbhz1kyuAACGPSc');\n }\n if (!hasSort) {\n p.push('sort:tracknum');\n }\n } else if (mode == 'albums') {\n if (!hasTags) {\n p.push(hasArtistId ? 'ArAlTP' : 'AlTP');\n }\n if (!hasSort) {\n p.push(`sort:album`);\n }\n } else if (mode == 'playlists') {\n if (!hasTags) {\n p.push('PlTP');\n }\n } else if (!hasTags) {\n if (mode == 'artists' || mode == 'vaalbums') {\n p.push('ArTP');\n if (!hasLibraryId && !hasNonArtistRole) {\n p.push('include_online_only_artists:1');\n }\n } else if (mode == 'years' || mode == 'genres') {\n p.push('tags:s');\n }\n }\n cmd = { command: c, params: p };\n }\n if (cmd.params.length > 0) {\n for (var i = 0, len = cmd.params.length; i < len; ++i) {\n cmd.params[i] = cmd.params[i]\n .replace('ArAlTP', 'tags:aajlqswyKRSSW2')\n .replace('ArTP', 'tags:s')\n .replace('PlTP', 'tags:suxE')\n .replace('AlTP', 'tags:ajlqswyKS2');\n }\n }\n cmd.params.push('menu:1');\n cmd.params.push('library_id:-1');\n return { ...cmd };\n}\n", "{\n \"name\": \"iobroker.squeezeboxrpc\",\n \"version\": \"2.0.2\",\n \"description\": \"ioBroker Logitech Squeezebox Adapter over JSON/RPC-Protocol\",\n \"author\": {\n \"name\": \"oweitman\",\n \"email\": \"oweitman@gmx.de\"\n },\n \"homepage\": \"https://github.com/oweitman/ioBroker.squeezeboxrpc\",\n \"license\": \"MIT\",\n \"keywords\": [\n \"ioBroker\",\n \"squeezebox\",\n \"LMS\",\n \"Logitech Media Server\",\n \"Lyrion Media Server\",\n \"music server\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/oweitman/ioBroker.squeezeboxrpc\"\n },\n \"engines\": {\n \"node\": \">= 22\"\n },\n \"dependencies\": {\n \"@iobroker/adapter-core\": \"^3.4.3\",\n \"jayson\": \"^4.3.0\",\n \"lodash\": \"^4.18.1\",\n \"super\": \"^0.2.3\"\n },\n \"devDependencies\": {\n \"@alcalzone/release-script\": \"^5.2.1\",\n \"@alcalzone/release-script-plugin-iobroker\": \"^5.2.0\",\n \"@alcalzone/release-script-plugin-license\": \"^5.2.2\",\n \"@alcalzone/release-script-plugin-manual-review\": \"^5.2.0\",\n \"@iobroker/adapter-dev\": \"^1.5.0\",\n \"@iobroker/build-tools\": \"^3.0.1\",\n \"@iobroker/eslint-config\": \"^2.2.0\",\n \"@iobroker/testing\": \"^5.2.2\",\n \"@tsconfig/node22\": \"^22.0.5\",\n \"@types/node\": \"^22.20.1\",\n \"@types/proxyquire\": \"^1.3.31\",\n \"proxyquire\": \"^2.1.3\",\n \"typescript\": \"~5.9.3\"\n },\n \"main\": \"squeezeboxrpc.js\",\n \"files\": [\n \"admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).{json,json5}\",\n \"admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}\",\n \"lib/\",\n \"widgets/*.html\",\n \"widgets/!(node_modules)/**/build/*.{js,map}\",\n \"widgets/!(node_modules)/**/css/*.css\",\n \"widgets/!(node_modules)/**/img/*.{png,svg,jpg}\",\n \"widgets/vis2squeezeboxrpc/\",\n \"www/\",\n \"io-package.json\",\n \"LICENSE\",\n \"main.js\"\n ],\n \"scripts\": {\n \"test:js\": \"mocha --config test/mocharc.custom.json \\\"*.test.js\\\" \\\"test/**/*.test.js\\\"\",\n \"test:package\": \"mocha test/package --exit\",\n \"test:integration\": \"mocha test/integration --exit\",\n \"test\": \"npm run test:js && npm run test:package\",\n \"check\": \"tsc --noEmit -p tsconfig.check.json\",\n \"lint\": \"npm run lint-adapter && npm run lint-vis1widgets && npm run lint-vis2widgets\",\n \"lint-adapter\": \"eslint -c eslint.config.mjs . --ignore-pattern src-widgets/ --ignore-pattern widgets/squeezeboxrpc/js/ --ignore-pattern widgets/vis2squeezeboxrpc/\",\n \"lint-vis1widgets\": \"eslint -c eslint.config.mjs widgets/squeezeboxrpc/js\",\n \"lint-vis2widgets\": \"cd src-widgets && npm run lint && cd ..\",\n \"npm\": \"npm run npm:main && npm run npm:vis1widgets && npm run npm:vis2widgets\",\n \"npm:main\": \"npm i\",\n \"npm:vis1widgets\": \"npm install --prefix widgets\",\n \"npm:vis2widgets\": \"cd src-widgets && npm i && cd ..\",\n \"devupload\": \"dev-server upload\",\n \"build\": \"npm run build-vis1widgets && npm run build-vis2widgets\",\n \"buildx\": \"npm run build-vis1widgets \",\n \"build-vis1widgets\": \"npm run build --prefix widgets\",\n \"build-vis2widgets\": \"node tasks --javascript-vite\",\n \"dev:upload\": \"dev-server upload\",\n \"dev:run\": \"dev-server run\",\n \"dev:watch\": \"dev-server watch --noStart\",\n \"dev:watchvis2widgets\": \"npm run start --prefix src-widgets\",\n \"dev:watchvis1widgets\": \"npm run watch --prefix widgets\",\n \"prepublishOnly\": \"npm run build\",\n \"repochecker\": \"npx github:oweitman/ioBroker.repochecker https://github.com/oweitman/ioBroker.squeezeboxrpc --local --noinfo\",\n \"translate\": \"translate-adapter\",\n \"translate-widgets\": \"node ./bin/translate.js --source widgets/squeezeboxrpc/myi18n/en.json --format single\",\n \"translate-lib\": \"node ./bin/translate.js --source lib/i18n/ --format multi\",\n \"release\": \"release-script --all\",\n \"release:2x\": \"release-script --all --branch-pattern release2x\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/oweitman/ioBroker.squeezeboxrpc/issues\"\n },\n \"readmeFilename\": \"README.md\"\n}\n", "'use strict';\n/* globals $,window,document */\n/*\n var fontStyle = '12px \"Courier New\", monospace'\n var lineHeight = 15\n\n var picWidth = 50;\n var picHeight = 50;\n var test1 = \"Squeeze Work\";\n var test2 = \"SqueezeWork\";\n var test3 = \"aaa- aaa - aaa aaa aaa\";\n $('body').append(createTextImage(test1,fontStyle,picWidth,picHeight));\n */\n\n/**\n * Searches for the first occurrence of a given regular expression in the\n * string from the given start position. If the regex is not found, returns -1.\n *\n * @param regex The regular expression to search for\n * @param [startpos] The position to start the search from\n * @returns The position of the first match or -1 if not found\n */\nString.prototype.regexIndexOf = function (regex, startpos) {\n const indexOf = this.substring(startpos || 0).search(regex);\n return indexOf >= 0 ? indexOf + (startpos || 0) : indexOf;\n};\n\n/**\n * Wordwrap a given string, with options to wrap camel case words and set\n * the width of the output.\n *\n * @param str - The string to wordwrap\n * @param width - The width of the output\n * @param [opt] - Options object\n * @param [opt.wrapCamelCase] - Whether to wrap camel case words\n * @returns The wordwrapped string\n */\nfunction wordwrap(str, width, opt) {\n opt = opt || {};\n const splitChars = [' ', '-', '\\t'];\n if (opt.wrapCamelCase) {\n str = str.replace(/([a-z])([A-Z])/gm, '$1 $2');\n }\n const words = explode(str, splitChars);\n let curLineLength = 0;\n let strBuilder = '';\n for (let i = 0; i < words.length; i += 1) {\n let word = words[i];\n if (curLineLength + word.length > width) {\n if (curLineLength > 0) {\n strBuilder += '\\n';\n curLineLength = 0;\n }\n while (word.Length > width) {\n strBuilder += `${word.substring(0, width - 1)}-`;\n word = word.substring(width - 1);\n strBuilder += '\\n';\n }\n word = word.trimStart();\n }\n if (curLineLength == 0 && /^\\s+$/.test(word)) {\n word = word.trimStart();\n }\n strBuilder += word;\n curLineLength += word.length;\n }\n return strBuilder;\n}\n\n/**\n * Split a string into parts where each part is either a word or a whitespace/dash character.\n * If a whitespace/dash character occurs between two words, it is put into its own part.\n * If a whitespace/dash character occurs at the end of a word, it is put into the same part as the word.\n *\n * @param str The string to split.\n * @returns An array of string parts.\n */\nfunction explode(str) {\n const parts = [];\n let startIndex = 0;\n\n while (true) {\n const index = str.regexIndexOf(/[ |\\t|-]/gm, startIndex);\n if (index == -1) {\n parts.push(str.substring(startIndex));\n return parts;\n }\n const word = str.substring(startIndex, startIndex + index - startIndex);\n const nextChar = str.substring(index, index + 1)[0];\n\n // Dashes and the likes should stick to the word occuring before it. Whitespace doesn't have to.\n if (/^\\s+$/.test(nextChar)) {\n parts.push(word);\n parts.push(nextChar);\n } else {\n parts.push(word + nextChar);\n }\n startIndex = index + 1;\n }\n}\n\n/**\n * Calculates the height metrics of the text using the specified font.\n *\n * This function creates a temporary DOM structure to measure the ascent,\n * descent, and total height of the text \"Hg\" rendered with the given font.\n *\n * @param font - An object representing the font, which provides a method\n * to get the font string.\n * @returns An object containing the ascent, descent, and total height\n * of the text, with properties:\n * - ascent: The distance from the baseline to the top of the text.\n * - descent: The distance from the baseline to the bottom of the text.\n * - height: The total height of the text.\n */\nconst getTextHeight = function (font) {\n const text = $('<span>Hg</span>').css({ font: font.getfont() });\n const block = $('<div style=\"display: inline-block; width: 1px; height: 0px;\"></div>');\n\n const div = $('<div></div>');\n div.append(text, block);\n\n const body = $('body');\n body.append(div);\n const result = {};\n try {\n block.css({ verticalAlign: 'baseline' });\n result.ascent = block.offset().top - text.offset().top;\n\n block.css({ verticalAlign: 'bottom' });\n result.height = block.offset().top - text.offset().top;\n\n result.descent = result.height - result.ascent;\n } finally {\n div.remove();\n }\n return result;\n};\n/**\n * @param text - The text to measure.\n * @param font - The font to use when measuring the text.\n * @returns The width of the text.\n */\nexport function getTextWidth(text, font) {\n const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'));\n const context = canvas.getContext('2d');\n context.font = font.getfont();\n const metrics = context.measureText(text);\n return metrics.width;\n}\n\n/** Class representing a Font. */\nexport class Font {\n /**\n * Creates a Font object for the given element.\n *\n * @param elem the element to get the font string from\n */\n constructor(elem) {\n this.span = document.createElement('span');\n const fontstr = this.getFontString(elem[0]);\n this.span.style.font = fontstr;\n this.measure = getTextHeight(this);\n this.measure.width = getTextWidth('M', this);\n }\n /**\n * Retrieves the ascent value of the font.\n *\n * @returns {number} The ascent value of the font.\n */\n getAscent() {\n return this.measure.ascent;\n }\n /**\n * Retrieves the descent value of the font.\n *\n * @returns {number} The descent value of the font.\n */\n getDescent() {\n return this.measure.descent;\n }\n /**\n * Retrieves the width of the font.\n *\n * @returns {number} The width of the font.\n */\n getWidth() {\n return this.measure.width;\n }\n /**\n * Retrieves the height value of the font.\n *\n * @returns {number} The height value of the font.\n */\n getHeight() {\n return this.measure.height;\n }\n /**\n * Returns the current font string for the font.\n *\n * @returns The current font string.\n */\n getfont() {\n return this.span.style.font;\n }\n /**\n * Set the font string for the font.\n *\n * @param fontstr the new font string\n * @returns The Font object, to allow chaining.\n */\n setfont(fontstr) {\n this.span.style.font = fontstr;\n return this;\n }\n /**\n * Increase the font size of the font by one pixel.\n *\n * @returns The Font object, to allow chaining.\n */\n incFontSize() {\n this.span.style.fontSize = `${parseInt(this.span.style.fontSize) + 1}px`;\n return this;\n }\n /**\n * Decrease the font size of the font by one pixel.\n *\n * @returns The Font object, to allow chaining.\n */\n decFontSize() {\n this.span.style.fontSize = `${parseInt(this.span.style.fontSize) - 1}px`;\n return this;\n }\n /**\n * Given an element, returns the CSS font string for that element.\n *\n * @param elem - The element to get the font string for.\n * @returns The CSS font string, or 'normal 12px sans-serif' if no font style is set.\n */\n getFontString(elem) {\n const style = window.getComputedStyle(elem);\n let elementFont = style.getPropertyValue('font');\n\n if (elementFont) {\n return elementFont;\n }\n\n const fontStyle = style.getPropertyValue('font-style');\n const fontVariant = style.getPropertyValue('font-variant');\n const fontWeight = style.getPropertyValue('font-weight');\n const fontSize = style.getPropertyValue('font-size');\n const fontFamily = style.getPropertyValue('font-family');\n\n elementFont = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize} ${fontFamily}`.replace(/ +/g, ' ').trim();\n return elementFont ? elementFont : 'normal 12px sans-serif';\n }\n}\n\n/**\n * Returns the first visible background colour of an element or one of its\n * ancestors. This lets generated canvas images follow VIS widget styles as\n * well as user supplied global CSS.\n *\n * @param {HTMLElement} element element whose effective background is required\n * @param {string} fallback fallback colour when all ancestors are transparent\n * @returns {string} effective CSS background colour\n */\nexport function getEffectiveBackgroundColor(element, fallback = '#000000') {\n for (let current = element; current; current = current.parentElement) {\n const backgroundColor = window.getComputedStyle(current).backgroundColor;\n if (\n backgroundColor &&\n backgroundColor != 'transparent' &&\n backgroundColor != 'rgba(0, 0, 0, 0)' &&\n backgroundColor != 'rgba(0,0,0,0)'\n ) {\n return backgroundColor;\n }\n }\n return fallback;\n}\n\n/**\n * Keeps an explicitly customised colour, but replaces the legacy default with\n * the effective colour inherited from VIS/CSS.\n *\n * @param {string} configured configured widget colour\n * @param {string} legacyDefault legacy default value from the VIS template\n * @param {string} inherited effective colour inherited from the widget\n * @returns {string} colour to render\n */\nexport function resolveLegacyDefaultColor(configured, legacyDefault, inherited) {\n if (!configured || configured.toLowerCase() == legacyDefault.toLowerCase()) {\n return inherited;\n }\n return configured;\n}\n/**\n * Adjusts the font size to ensure that the given lines of text fit within the specified width.\n *\n * @param lines - An array of strings, each representing a line of text.\n * @param picWidth - The maximum width in pixels that the text should occupy.\n * @param font - An object representing the font, which has methods to increase and decrease font size.\n * @returns The adjusted font object with a size that fits the lines within the specified width.\n */\nfunction getGoodFontSize(lines, picWidth, font) {\n while (true) {\n const maxWidth = getMaxPixelWidth(lines, font);\n if (maxWidth > picWidth) {\n font.decFontSize();\n } else {\n return font;\n }\n }\n}\n/**\n * Create a canvas with the given lines, using the given font and dimensions,\n * but using a font size which will fit the text into the canvas.\n *\n * @param lines the lines of text to be rendered\n * @param font the font to use, or a string describing it\n * @param picWidth the width of the canvas\n * @param picHeight the height of the canvas\n * @param lineHeight the line height of the text\n * @param [opt] options, as follows:\n * @param [opt.style] css style to use for the canvas\n * @param [opt.style.direction] direction of text, either 'ltr' or 'rtl'\n * @param [opt.style.textAlign] text alignment, either 'start', 'end', 'left', 'right', or 'center'\n * @param [opt.style.color] color of the text\n * @param [opt.style.backgroundcolor] background color of the canvas\n * @returns the canvas element\n */\nfunction createCanvas(lines, font, picWidth, picHeight, lineHeight, opt) {\n opt = opt || {};\n const canvas = document.createElement('canvas');\n $('body').append(canvas);\n canvas.width = picWidth;\n canvas.height = picHeight;\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = opt.style ? opt.backgroundcolor : 'black';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.font = font.getfont();\n ctx.fillStyle = opt.style ? opt.style.color : 'white';\n ctx.textAlign = opt.style ? opt.style.textAlign : 'center';\n let x = 0;\n if (opt.style) {\n if (opt.style.direction == 'ltr') {\n if (opt.style.textAlign == 'start' || opt.style.textAlign == 'left') {\n x = 0;\n }\n if (opt.style.textAlign == 'end' || opt.style.textAlign == 'right') {\n x = picWidth;\n }\n if (opt.style.textAlign == 'center') {\n x = picWidth / 2;\n }\n }\n if (opt.style.direction == 'rtl') {\n if (opt.style.textAlign == 'end' || opt.style.textAlign == 'left') {\n x = 0;\n }\n if (opt.style.textAlign == 'start' || opt.style.textAlign == 'right') {\n x = picWidth;\n }\n if (opt.style.textAlign == 'center') {\n x = picWidth / 2;\n }\n }\n } else {\n x = picWidth / 2;\n }\n const y = font.getDescent() + Math.floor((picHeight - lines.length * lineHeight) / 2);\n ctx.textBaseline = 'top';\n for (let i = 0; i < lines.length; i++) {\n ctx.fillText(lines[i], x, y + i * lineHeight);\n }\n return canvas;\n}\n/**\n * Return the maximum number of characters in any line of the given array of\n * strings.\n *\n * @param lines an array of strings, each a line of text.\n * @returns the maximum number of characters in any line.\n */\nfunction getMaxChars(lines) {\n return lines.reduce(\n function (acc, cur) {\n return Math.max(acc, cur.length);\n }.bind(this),\n 0,\n );\n}\n/**\n * Return the maximum width in pixels of the given lines of text, using the\n * given font. The width is calculated by summing the widths of each line of\n * text.\n *\n * @param lines an array of strings, each a line of text.\n * @param font the font to use, or a string describing it.\n */\nfunction getMaxPixelWidth(lines, font) {\n return lines.reduce(\n function (acc, cur) {\n return Math.max(acc, getTextWidth(cur.trim(), font));\n }.bind(this),\n 0,\n );\n}\n\n/**\n * Create a canvas with the given text, using the given font and dimensions,\n * but using a font size which will fit the text into the canvas.\n *\n * @param text the text to be rendered\n * @param font the font to use, or a string describing it\n * @param picWidth the width of the canvas\n * @param picHeight the height of the canvas\n * @param [opt] options, as follows:\n * @param [opt.style] css style to use for the canvas\n * @param [opt.style.direction] direction of text, either 'ltr' or 'rtl'\n * @param [opt.style.textAlign] text alignment, either 'start', 'end', 'left', 'right', or 'center'\n * @param [opt.style.color] color of the text\n * @param [opt.style.backgroundcolor] background color of the canvas\n * @param [opt.wrapCamelCase] whether to wrap camel case words\n * @returns the canvas element\n */\nexport function createTextImage(text, font, picWidth, picHeight, opt) {\n opt = opt || {};\n font = typeof font == 'string' ? new Font(font) : font;\n const lineHeight = font.getHeight(); //getTextHeight(font).height;\n const charWidth = font.getWidth(); //getTextWidth(\"M\", font);\n const maxChars = picWidth / charWidth;\n let maxLines = picHeight / lineHeight - 1;\n maxLines = maxLines < 0 ? 1 : maxLines;\n let lines;\n if (picHeight >= picWidth) {\n for (\n let textWidth = 1;\n (lines = wordwrap(text, textWidth, opt).split('\\n')) && maxLines + 1 < lines.length;\n textWidth++\n ) {\n //count textWidth\n }\n } else {\n for (\n let textWidth = 1;\n (lines = wordwrap(text, textWidth, opt).split('\\n')) && getMaxChars(lines) < maxChars && lines.length > 1;\n textWidth++\n ) {\n /* empty */\n }\n }\n const goodFont = getGoodFontSize(lines, picWidth, font);\n return createCanvas(lines, goodFont, picWidth, picHeight, lineHeight, opt);\n}\n", "/* globals $,vis */\n'use strict';\n\nimport { parseRequestFactory } from '../sbClasses.js';\nimport { getTextWidth, Font } from '../textImage.js';\n\nexport const browser = {\n topitems: [\n {\n title: 'My Music',\n actions: JSON.stringify({ next: 'mymusic' }),\n id: 'myMusic',\n },\n {\n title: 'Radio',\n actions: JSON.stringify({ next: 'radio' }),\n id: 'radio',\n },\n {\n title: 'Favorites',\n actions: JSON.stringify({ next: 'favorites' }),\n id: 'favorites',\n },\n {\n title: 'Apps',\n actions: JSON.stringify({ next: 'apps' }),\n id: 'apps',\n },\n {\n title: 'Extra',\n actions: JSON.stringify({ next: 'extra' }),\n id: 'extra',\n },\n ],\n specialRangeHandling: [\n {\n mode: 'mode:floptracks',\n range: [0, 200],\n },\n {\n mode: 'mode:toptracks',\n range: [0, 200],\n },\n ],\n indexParam: [0, 25000],\n info: {},\n createWidget: async function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].browser.createWidget(widgetID, view, data, style);\n }, 100);\n }\n if (!this.info[widgetID]) {\n this.info[widgetID] = {\n history: [],\n data: data,\n style: style,\n view: view,\n };\n }\n vis.binds['squeezeboxrpc'].debug = data.debug || false;\n vis.binds['squeezeboxrpc'].fetchResults = data.debugwithFetchResults || false;\n\n this.info[widgetID].instance = data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes(\n $div,\n data.widgetPlayer,\n );\n let ainstance = this.info[widgetID].instance;\n if (!ainstance) {\n return;\n }\n const playername = await vis.binds['squeezeboxrpc'].getPlayerNameAsync(data.widgetPlayer);\n const state = `${ainstance[0]}.${ainstance[1]}.Players` + `.${playername}.PlayerID`;\n this.info[widgetID].playerid = await vis.binds['squeezeboxrpc'].getPlayerID(state);\n this.goDeeper(widgetID, { id: 'home', title: 'Home', params: null });\n },\n async goDeeper(widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`goDeeper ${widgetID}`);\n let children = await this.fetchChildren(widgetID, data);\n if (!children) {\n vis.binds['squeezeboxrpc'].debug && console.log(`End of tree reached ${widgetID}`);\n return;\n }\n this.info[widgetID].history.push(data);\n this.render(widgetID, children);\n },\n async goBack(widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`goBack ${widgetID}`);\n if (this.info[widgetID].history.length > 1) {\n this.info[widgetID].history.pop();\n }\n if (this.info[widgetID].history.length == 0) {\n return;\n }\n let data = this.info[widgetID].history[this.info[widgetID].history.length - 1];\n let children = await this.fetchChildren(widgetID, data);\n this.render(widgetID, children);\n },\n async fetchChildren(widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`fetchChildren ${widgetID}`);\n let items = {};\n switch (data.id || '') {\n case 'home':\n items = this.topitems;\n // // title = target.title;\n break;\n case 'radio':\n items = await vis.binds['squeezeboxrpc'].browser.browseradio(widgetID, data);\n break;\n case 'favorites':\n items = await vis.binds['squeezeboxrpc'].browser.browserfavorites(widgetID, data);\n break;\n case 'apps':\n items = await vis.binds['squeezeboxrpc'].browser.browseapps(widgetID, data);\n break;\n case 'myMusic':\n case 'extra':\n items = await vis.binds['squeezeboxrpc'].browser.browsemenu(widgetID, data);\n break;\n default:\n if (data.actions) {\n items = await vis.binds['squeezeboxrpc'].browser.browseparametermenu(widgetID, data);\n }\n break;\n }\n if (!items) {\n return;\n }\n return items.filter(el => el);\n },\n browseapps: async function (widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browseapps ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['myapps', 'items', 0, '25000', 'menu:1'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n browseradio: async function (widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browseradio ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['radios', 0, '25000', 'menu:radio'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n browserfavorites: async function (widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browserfavorites ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['favorites', 'items', 0, '25000', 'menu:favorites'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n browsemenu: async function (widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browsemenu ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const data1 = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['menu', 'items', 0, '25000', 'direct:1'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', data1);\n let filter = item => item.item.node === data.id;\n let menu = parseRequestFactory(request);\n return menu\n .getMenuItems()\n .filter(filter)\n .sort((a, b) => a.item.weight - b.item.weight);\n //return this.parseResult(request, filter, data.id);\n },\n browseparametermenu: async function (widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browseparametermenu ${widgetID}`);\n let parameter = JSON.parse(data.actions)['next'];\n let ainstance = this.info[widgetID].instance;\n let range = [...this.indexParam];\n if (parameter.params) {\n this.specialRangeHandling.forEach(item => {\n if (parameter.params.includes(item.mode)) {\n range = item.range;\n }\n });\n } /* else {\n return;\n } */\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: [...parameter.command, ...range, ...parameter.params],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n clickhandler: async function (event, widgetID, func, id) {\n vis.binds['squeezeboxrpc'].debug && console.log(`clickhandler ${widgetID} ${func} ${id}`);\n let child;\n\n event.preventDefault();\n event.stopPropagation();\n if (id) {\n child = this.info[widgetID].currentChildren.find(c => c.id == id);\n }\n if (func == 'next') {\n /* if (!child.param) {\n return;\n } */\n await this.goDeeper(widgetID, child);\n } else if (func == 'back') {\n await this.goBack(widgetID);\n return;\n } else {\n await this.doAction(widgetID, child, func, id);\n return;\n }\n },\n doAction: async function (widgetID, child, func /* , id */) {\n vis.binds['squeezeboxrpc'].debug && console.log(`doAction`);\n let actions = JSON.parse(child.actions);\n let parameter = actions[func];\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: [...parameter.command, ...parameter.params],\n };\n /* let request = */ await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n },\n render(widgetID, children) {\n vis.binds['squeezeboxrpc'].debug && console.log(`render ${widgetID}`);\n let backTitle = '--';\n backTitle = this.info[widgetID].history.reduce((acc, val, i) => `${acc} ${i == 0 ? '' : '/'} ${val.title}`, '');\n const font = new Font($(`#${widgetID}`));\n let textwidth = getTextWidth(`...${backTitle}`, font);\n let widgetwidth = $(`#${widgetID}`).width();\n\n this.info[widgetID].currentChildren = children;\n let text = '';\n\n text += `\n <style>\n /* Grundlegendes Layout der Listen-Container */\n #${widgetID} .sqbrowser-list-container {\n width: 100%;\n // max-width: 600px; /* Beispiel: feste max-Breite */\n margin: 0 auto; /* zentriert auf der Seite */\n box-sizing: border-box;\n }\n #${widgetID} .sqbrowser-parent-directory {\n position: sticky; /* \"Klebt\" an einer definierten Position */\n top: 0; /* Fixiert oben im Container */\n padding: 0rem 0rem;\n z-index: 10; /* Damit sie auch oben bleibt, falls andere Elemente dar\u00FCberliegen k\u00F6nnten */\n border-bottom: 1px solid #ccc;\n /* background-color: black; */\n cursor: pointer;\n }\n #${widgetID} .sqbrowser-ellipsis {\n white-space: nowrap;\n text-overflow: ellipsis;\n direction: rtl;\n overflow: hidden;\n }\n #${widgetID} .sqbrowser-scrollable-area {\n /* Hier legen wir die H\u00F6he fest, ab der gescrollt werden soll */\n /* max-height: 300px; */ /* Beispiel: 300px */\n overflow-y: auto; /* Vertikales Scrollen bei \u00DCberlauf */\n padding: 0 0rem;\n }\n /* Einzelne List-Items */\n #${widgetID} .sqbrowser-list-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.2rem;\n margin: 0.2rem 0;\n // background-color: #f8f8f8;\n border: 1px solid #ccc;\n border-radius: 4px;\n z-index: 1;\n }\n\n #${widgetID} .sqbrowser-list-item[onclick] {\n cursor: pointer; /* signalisiert, dass klickbar ist */\n }\n\n /* Der Text-Bereich innerhalb eines List-Items */\n #${widgetID} .sqbrowser-list-item-content {\n flex: 1; /* soll den verf\u00FCgbaren Platz f\u00FCllen */\n margin-right: 1rem; /* Abstand zu den Buttons */\n white-space: nowrap; /* verhindert Zeilenumbruch */\n overflow: hidden; /* versteckt \u00FCberflie\u00DFenden Text */\n text-overflow: ellipsis; /* f\u00FCgt \u201E...\u201C ein, wenn Text nicht passt */\n }\n\n /* Button-Gruppe auf der rechten Seite */\n #${widgetID} .sqbrowser-button-group {\n display: flex;\n align-items: center;\n }\n\n /* Die Buttons selbst */\n #${widgetID} .sqbrowser-action-btn {\n margin-left: 0.2rem;\n padding: 0.1rem 0.2rem;\n cursor: pointer;\n border: 1px solid #666;\n background-color: #eee;\n border-radius: 3px;\n font-size: 1rem;\n }\n #${widgetID} svg:active { \n transform: scale(0.8, 0.8);\n transform-origin: 50% 50%;\n }\n\n /* Drei-Punkte-Button standardm\u00E4\u00DFig ausgeblendet, \n nur sichtbar werden, wenn nicht genug Platz f\u00FCr Button2 ist */\n #${widgetID} .sqbrowser-more-btn {\n display: none; /* wird per Media Query eingeblendet */\n }\n #${widgetID} .sqbrowser-btn-svg {\n width: 1rem;\n height: 1rem;\n margin: 0px 1px;\n cursor: pointer;\n }\n #${widgetID} .sqbrowser-btn-svg-action {\n border: 1px solid white;\n }\n #${widgetID} .sqbrowser-btn-svg-menu {\n display: inline-block;\n vertical-align: middle;\n height: fit-content;\n }\n </style>\n `;\n text += ` \n <div class=\"sqbrowser-list-container\">\n <div class=\"sqbrowser-parent-directory ${textwidth - 10 > widgetwidth ? 'sqbrowser-ellipsis' : ''}\" onclick=\"vis.binds.squeezeboxrpc.browser.clickhandler(event, '${widgetID}', 'back')\">\n <div class=\"sqbrowser-btn-svg sqbrowser-btn-svg-menu\">\n ${vis.binds['squeezeboxrpc'].svg.menuback}\n </div>\n <span>${backTitle}</span>\n </div>\n <div class=\"sqbrowser-scrollable-area\">\n `;\n for (let i = 0; i < children.length; i++) {\n let buttons;\n if (children[i].actions) {\n buttons = JSON.parse(children[i].actions);\n }\n let click = '';\n if (buttons && buttons.next) {\n click = children[i].actions\n ? `onclick=\"vis.binds.squeezeboxrpc.browser.clickhandler(event, '${widgetID}', 'next','${children[i].id}')\"`\n : ``;\n }\n text += /* html */ `\n <div\n class=\"sqbrowser-list-item\"\n ${click}\n >\n <div class=\"sqbrowser-list-item-content\">${children[i].title}</div>\n <div class=\"sqbrowser-button-group\">\n `;\n\n if (buttons) {\n let actions = [\n { id: 'next', svg: 'next' },\n { id: 'play', svg: 'play' },\n { id: 'add', svg: 'add' },\n ];\n for (let action = 0; action < actions.length; action++) {\n if (buttons[actions[action].id]) {\n text += `\n <div class=\"sqbrowser-btn-svg sqbrowser-btn-svg-action\" onclick=\"vis.binds.squeezeboxrpc.browser.clickhandler(event, '${widgetID}', '${actions[action].id}','${children[i].id}')\">\n ${vis.binds['squeezeboxrpc'].svg[actions[action].svg]}\n </div>\n `;\n }\n }\n }\n text += ` \n </div>\n </div>\n `;\n }\n text += /* html */ `\n </div></div>\n `;\n $(`#${widgetID}`).html(text);\n },\n parseResult: function (request, filter, rootmenu) {\n vis.binds['squeezeboxrpc'].debug && console.log(`parseResult`);\n let result = request.result;\n if (result.years_loop) {\n let items = result.years_loop;\n return items.map(item => {\n return {\n id: item.year,\n title: `${item.year}`,\n type: 'years',\n favorites_url: item.facorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.works_loop) {\n let items = result.works_loop;\n return items.map(item => {\n return {\n id: `work_id:${item.work_id}`,\n title: `${item.favorites_title}`,\n type: 'work',\n favorites_url: item.facorites_url,\n albumid: item.album_id,\n composer: item.composer,\n composer_id: item.composer_id,\n work: item.work,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.genres_loop) {\n let items = result.genres_loop;\n return items.map(item => {\n return {\n id: item.id,\n title: `${item.genre}`,\n type: 'genre',\n favorites_url: item.facorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.albums_loop) {\n let items = result.albums_loop;\n return items.map(item => {\n return {\n id: item.id,\n title: `${item.artist} / ${item.album} (${item.year})`,\n image: `/music/${item.artwork_track_id}/cover_300x300_f`,\n type: 'album',\n favorites_url: item.facorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.artists_loop) {\n let items = result.artists_loop;\n return items.map(item => {\n return {\n id: item.id,\n title: item.artist,\n image: `/imageproxy/mai/artist/${item.id}/image_300x300_f`,\n type: 'artist',\n favorites_url: item.favorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.item_loop) {\n let items = result.item_loop;\n const style = result.window?.windowStyle || '';\n //=='icon_list'){\n if (filter) {\n items = items.filter(filter);\n }\n if (rootmenu == 'myMusic' && style == 'icon_list') {\n return items.map(item => {\n return {\n id: item.commonParams.track_id,\n type: 'track',\n title: item.text.replace('\\n', ' - '),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n if (rootmenu == 'myMusic' && (style == 'text_list' || style == 'home_menu')) {\n return items.map(item => {\n if (item.type == 'audio') {\n return {\n id: item.params.item_id,\n type: 'track',\n title: item.text.replace('\\n', ' - '),\n icon: null,\n rootmenu: rootmenu,\n };\n }\n if (item.type == 'playlist') {\n let cmd = {\n command: ['browselibrary', 'items'],\n params: ['menu:browselibrary', 'mode:bmf', ...this.object2Array(item.params)],\n };\n return {\n id: item.params.item_id,\n type: 'playlist',\n title: `(D) ${item.text.replace('\\n', ' - ')}`,\n param: JSON.stringify(cmd),\n icon: null,\n rootmenu: rootmenu,\n };\n }\n });\n }\n if (style == '' && rootmenu == 'myMusic') {\n items = items.sort((a, b) => a.weight - b.weight);\n return items.map(item => {\n return {\n id: item.id,\n type: 'menu',\n title: item.text,\n param: JSON.stringify(this.translateMyMusicParameters(item.actions.go)),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n if (style == '' && rootmenu == 'radio') {\n items = items.sort((a, b) => a.weight - b.weight);\n return items.map(item => {\n return {\n id: item.text,\n type: 'radio',\n title: item.text,\n param: JSON.stringify(this.translateMyMusicParameters(item.actions.go)),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n if (rootmenu == 'radio' && style == 'text_list') {\n return items.map(item => {\n return {\n id: item.text,\n type: 'radio',\n title: item.text.replace('\\n', ' - '),\n param: JSON.stringify(this.translateMyMusicParameters(item.actions.go)),\n icon: null,\n rootmenu: rootmenu,\n };\n });\n }\n if (rootmenu == 'radio' && style == 'icon_list') {\n return items.map(item => {\n return {\n id: item.params.item_id,\n type: 'track',\n title: item.text.replace('\\n', ' - '),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n }\n },\n\n object2Array: function (obj) {\n return Object.keys(obj).map(function (key) {\n return `${key}:${obj[key]}`;\n });\n },\n};\n", "'use strict';\n\nfunction normalizeItem(item) {\n const id = String(item?.id || '').trim();\n return id\n ? {\n id,\n enabled: item.enabled !== false,\n text: String(item.text || ''),\n image: String(item.image || ''),\n }\n : null;\n}\n\n/**\n * Parse a persisted item configuration.\n *\n * @param value persisted value\n */\nexport function parseItemConfiguration(value) {\n if (!value) {\n return null;\n }\n try {\n const parsed = typeof value == 'string' ? JSON.parse(value) : value;\n if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.items)) {\n return null;\n }\n const items = [];\n parsed.items.forEach(item => {\n const normalized = normalizeItem(item);\n if (normalized && !items.some(existing => existing.id == normalized.id)) {\n items.push(normalized);\n }\n });\n return {\n version: 1,\n defaultId: String(parsed.defaultId || ''),\n items,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Serialize an item configuration for a VIS widget attribute.\n *\n * @param configuration item configuration\n */\nexport function serializeItemConfiguration(configuration) {\n return JSON.stringify({\n version: 1,\n defaultId: String(configuration.defaultId || ''),\n items: configuration.items.map(normalizeItem).filter(Boolean),\n });\n}\n\n/**\n * Merge saved items with currently discovered IDs without changing saved data.\n *\n * @param configuration saved configuration\n * @param discoveredItems currently available items\n */\nexport function mergeConfiguredItems(configuration, discoveredItems) {\n const discovered = new Map(\n discoveredItems\n .map(item => {\n const source = typeof item == 'string' ? { id: item } : item;\n const normalized = normalizeItem(source);\n return normalized ? { ...source, ...normalized } : null;\n })\n .filter(Boolean)\n .map(item => [item.id, item]),\n );\n const result = (configuration?.items || []).map(item => {\n const remote = discovered.get(item.id);\n discovered.delete(item.id);\n return {\n ...remote,\n ...item,\n discoveredImage: remote?.image || '',\n available: !!remote,\n };\n });\n discovered.forEach(item => result.push({ ...item, enabled: true, available: true }));\n return result;\n}\n\n/**\n * Return enabled and currently available items in their configured order.\n *\n * @param configuration saved configuration\n * @param discoveredItems currently available items\n */\nexport function visibleConfiguredItems(configuration, discoveredItems) {\n return mergeConfiguredItems(configuration, discoveredItems).filter(\n item => item.enabled !== false && item.available,\n );\n}\n\nfunction legacyList(value) {\n return String(value || '')\n .split(',')\n .map(item => item.trim())\n .filter(Boolean);\n}\n\n/**\n * Convert legacy positional Players settings in memory.\n *\n * @param data legacy widget data\n * @param playerNames discovered player names\n */\nexport function legacyPlayerConfiguration(data, playerNames) {\n const configuredIndices = legacyList(data.viewindex);\n const orderedIndices = configuredIndices.length ? configuredIndices : playerNames.map((_, index) => String(index));\n const enabled = new Set(orderedIndices);\n const items = [];\n orderedIndices.forEach(value => {\n const index = Number(value);\n if (\n Number.isInteger(index) &&\n playerNames[index] !== undefined &&\n !items.some(item => item.id == playerNames[index])\n ) {\n items.push({\n id: playerNames[index],\n enabled: true,\n text: String(data[`buttonsText${index + 1}`] || ''),\n image: String(data[`buttonsImage${index + 1}`] || ''),\n });\n }\n });\n playerNames.forEach((id, index) => {\n if (!items.some(item => item.id == id)) {\n items.push({\n id,\n enabled: !configuredIndices.length || enabled.has(String(index)),\n text: String(data[`buttonsText${index + 1}`] || ''),\n image: String(data[`buttonsImage${index + 1}`] || ''),\n });\n }\n });\n const defaultIndex = Number(data.defaultPlayer);\n const defaultId = playerNames[defaultIndex] || String(data.defaultPlayer || '') || items[0]?.id || '';\n return { version: 1, defaultId, items };\n}\n\n/**\n * Convert legacy Favorites settings in memory.\n *\n * @param data legacy widget data\n * @param favorites discovered favorites\n */\nexport function legacyFavoriteConfiguration(data, favorites) {\n const discoveredIds = favorites.map(favorite => favorite.id);\n const configuredIds = legacyList(data.viewindex);\n const orderedIds = configuredIds.length ? configuredIds : discoveredIds;\n const items = [];\n orderedIds.forEach((id, position) => {\n const favorite = favorites.find(item => item.id == id);\n if (favorite && !items.some(item => item.id == id)) {\n items.push({\n id,\n enabled: true,\n text: String(data[`buttonsText${position + 1}`] || ''),\n image: String(data[`buttonsImage${position + 1}`] || ''),\n });\n }\n });\n favorites.forEach(favorite => {\n if (!items.some(item => item.id == favorite.id)) {\n items.push({ id: favorite.id, enabled: false, text: '', image: '' });\n }\n });\n return { version: 1, defaultId: '', items };\n}\n\n/**\n * Return a reordered copy of the item list.\n *\n * @param items configured items\n * @param index source index\n * @param offset movement offset\n */\nexport function moveConfiguredItem(items, index, offset) {\n const target = index + offset;\n if (index < 0 || target < 0 || index >= items.length || target >= items.length) {\n return items;\n }\n const result = items.slice();\n const [item] = result.splice(index, 1);\n result.splice(target, 0, item);\n return result;\n}\n", "/* globals $,vis,window */\n'use strict';\n\nimport { createTextImage, Font } from '../textImage.js';\nimport { legacyFavoriteConfiguration, parseItemConfiguration, visibleConfiguredItems } from '../itemConfiguration.js';\n\nexport const favorites = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].favorites.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n // Keep the saved configuration and already resolved runtime bindings in\n // a mutable object. Resolved values must win over their raw expressions.\n data = { ...vis.views[view].widgets[widgetID].data, ...(data || {}) };\n style = vis.views[view].widgets[widgetID].style;\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n const key = `${ainstance[0]}.${ainstance[1]}.` + `Favorites.*`;\n vis.conn.gettingStates = 0;\n vis.conn.getStates(\n key,\n function (err, obj) {\n let favorites = this.getFavorites(obj, ainstance);\n favorites = this.filterFavorites(favorites);\n const configuration =\n parseItemConfiguration(data.favoriteConfiguration) || legacyFavoriteConfiguration(data, favorites);\n const configuredFavorites = visibleConfiguredItems(configuration, favorites);\n\n const editmodehelper = data.editmodehelper;\n const picWidth = data.picWidth;\n const picHeight = data.picHeight;\n const opacity = vis.editMode && editmodehelper ? 1 : data.opacity;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercolornormal = data.bordercolornormal;\n const bordercoloractive = data.bordercoloractive;\n const borderradius = data.borderradius;\n const buttonmargin = data.buttonmargin || '0px';\n\n let text = '';\n\n text += '<style>\\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += '}\\n';\n text += `#${widgetID} div div {\\n`;\n text += ' position: relative; \\n';\n text += ` margin: 0px ${buttonmargin} ${buttonmargin} 0px; \\n`;\n text += '}\\n';\n text += `#${widgetID} #${widgetID}container {\\n`;\n text += ' box-sizing: border-box;\\n';\n text += ' display: block;\\n';\n text += ' width: 100%;\\n';\n text += ' height: 100%;\\n';\n text += ' overflow: auto;\\n';\n text += ' scrollbar-width: thin;\\n';\n text += '}\\n';\n text += `#${widgetID} #${widgetID}container::-webkit-scrollbar {\\n`;\n text += ' width: 6px;\\n';\n text += ' height: 6px;\\n';\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"] {\\n`;\n text += ' display: none;\\n';\n text += '}\\n';\n text += `#${widgetID} img {\\n`;\n text += ` opacity: ${opacity};\\n`;\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornormal};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} canvas {\\n`;\n text += ` opacity: ${opacity};\\n`;\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornormal};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} img:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} canvas:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label img {\\n`;\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label canvas {\\n`;\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += '</style>\\n';\n\n text += `<div id=\"${widgetID}container\">`;\n for (let i = 0; i < configuredFavorites.length; i++) {\n const favorite = configuredFavorites[i];\n text += ' <div>';\n text += ` <input type=\"radio\" id=\"${widgetID}${favorite.id}\" name=\"${widgetID}\" value=\"${\n favorite.id\n }\" >`;\n text += ` <label for=\"${widgetID}${favorite.id}\">`;\n text += ' <span>';\n let favimage = favorite.image || favorite.discoveredImage || '';\n let favtext = favorite.id || '';\n let attrimage = favorite.image || '';\n let attrtext = favorite.text || '';\n\n favimage = favimage.trim();\n favtext = favtext.trim();\n attrimage = attrimage.trim();\n attrtext = attrtext.trim();\n\n const buttonsImage = attrimage || favimage;\n\n if (!attrtext && buttonsImage) {\n text += ` <img src=\"${buttonsImage}\">`;\n }\n text += ' </span>';\n text += ' </label>';\n if (vis.editMode && editmodehelper) {\n text += `<div style=\"position: absolute;top: 0;right: 0;background-color: black;color: white;border-width: 1px;border-color: white;border-style: solid;font-size: xx-small;padding: 1px;\">${\n favorite.id\n }</div>`;\n }\n text += ' </div>';\n }\n text += '</div>';\n\n $(`#${widgetID}`).html(text);\n\n const spans = $(`#${widgetID} span`);\n const font = new Font($(`#${widgetID}`));\n const opt = {};\n const computedStyle = window.getComputedStyle($(`#${widgetID}`)[0], null);\n\n opt.style = {\n color: style?.color || '#ffffff',\n direction: computedStyle.direction,\n textAlign: computedStyle.textAlign || 'center',\n };\n opt.backgroundcolor = data.buttonbkcolor || '#000000';\n for (let i = 0; i < configuredFavorites.length; i++) {\n const favorite = configuredFavorites[i];\n\n let favimage = favorite.image || favorite.discoveredImage || '';\n let favtext = `${favorite.id || ''}(${i})`;\n let attrimage = favorite.image || '';\n let attrtext = favorite.text || favorite.name || '';\n\n favimage = favimage.trim();\n favtext = favtext.trim();\n attrimage = attrimage.trim();\n attrtext = attrtext.trim();\n\n const buttonsImage = attrimage || favimage;\n\n const buttonsText = attrtext || favtext;\n if (attrtext || !buttonsImage) {\n $(spans[i]).append(createTextImage(buttonsText, font, picWidth, picHeight, opt));\n }\n }\n const favbtns = $(`input[name=${widgetID}]`);\n favbtns.off('change.favorite').on('change.favorite', fdata, function (event) {\n const fdata = event.data;\n const data = fdata.data;\n const favorite = this.value;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const state = `${ainstance[0]}.${ainstance[1]}.Players` + `.${playername}.cmdPlayFavorite`;\n //vis.conn._socket.emit('setState', state, favorite);\n vis.setValue(state, favorite);\n });\n }.bind(this),\n );\n },\n getFavorites: function (datapoints, ainstance) {\n const regex = new RegExp(`^${ainstance[0]}\\\\.${ainstance[1]}\\\\.Favorites`, '');\n return Object.keys(datapoints).reduce(\n function (acc, cur) {\n if (regex.test(cur)) {\n const key = cur.split('.')[3];\n const name = cur.split('.')[4];\n if (!acc[key]) {\n acc[key] = {};\n }\n acc[key][name] = this[cur].val;\n }\n return acc;\n }.bind(datapoints),\n [],\n );\n },\n filterFavorites: function (favorites) {\n favorites = Object.values(favorites);\n return favorites.filter(function (cur) {\n return cur.isaudio === 1;\n });\n },\n};\n", "/* globals $,vis,window */\n'use strict';\n\nimport { createTextImage, Font, getEffectiveBackgroundColor, resolveLegacyDefaultColor } from '../textImage.js';\nimport { legacyPlayerConfiguration, parseItemConfiguration, visibleConfiguredItems } from '../itemConfiguration.js';\n\nexport const players = {\n createWidget: async function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].players.createWidget(widgetID, view, data, style);\n }, 100);\n }\n // VIS may expose the saved widget configuration as a frozen object, while\n // the data passed to the renderer contains already resolved bindings.\n // Keep both in a mutable copy and prefer the resolved runtime values.\n data = { ...vis.views[view].widgets[widgetID].data, ...(data || {}) };\n style = vis.views[view].widgets[widgetID].style;\n data.ainstance = data.ainstance ? data.ainstance.split('.').slice(0, 2).join('.') : '';\n const ainstance = data.ainstance.split('.');\n if (ainstance[0] != 'squeezeboxrpc' || !ainstance[1]) {\n $div.html('Please select an instance');\n return;\n }\n\n const renderPlayers = function (playerNames) {\n const configuration =\n parseItemConfiguration(data.playerConfiguration) || legacyPlayerConfiguration(data, playerNames);\n const configuredPlayers = visibleConfiguredItems(configuration, playerNames);\n\n const picWidth = data.picWidth;\n const picHeight = data.picHeight;\n const opacity = data.opacity;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercoloractive = data.bordercoloractive;\n const borderradius = data.borderradius;\n const buttonmargin = data.buttonmargin || '0px';\n\n const defaultPlayer = configuredPlayers.some(player => player.id == configuration.defaultId)\n ? configuration.defaultId\n : configuredPlayers[0]?.id || '';\n if (data.formattype == 'formatselect') {\n let text = '';\n let option = '';\n option += '<option value=\"\"></option>';\n for (let i = 0; i < configuredPlayers.length; i++) {\n const buttonsText = configuredPlayers[i].text || configuredPlayers[i].id;\n option += `<option value=\"${configuredPlayers[i].id}\" ${\n configuredPlayers[i].id == defaultPlayer ? 'selected' : ''\n }>${buttonsText}</option>`;\n }\n text += `<select type=\"text\" id=\"${widgetID}select\">${option}</select>`;\n $(`#${widgetID}`).html(text);\n }\n if (data.formattype == 'formatbutton') {\n const widgetElement = $div[0];\n const computedStyle = window.getComputedStyle(widgetElement, null);\n const foregroundColor = computedStyle.color || '#ffffff';\n const backgroundColor = resolveLegacyDefaultColor(\n data.buttonbkcolor,\n '#000000',\n getEffectiveBackgroundColor(widgetElement, '#000000'),\n );\n const bordercolornormal = data.bordercolornormal;\n\n let text = '';\n\n text += '<style>\\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += '}\\n';\n text += `#${widgetID} div div {\\n`;\n text += ' position: relative; \\n';\n text += ` margin: 0px ${buttonmargin} ${buttonmargin} 0px; \\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"] {\\n`;\n text += ' display: none;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span {\\n`;\n text += ' display: inline-block;\\n';\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornormal};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += ' overflow: hidden;\\n';\n text += ' vertical-align: top;\\n';\n text += '}\\n';\n text += `#${widgetID} img, #${widgetID} canvas {\\n`;\n text += ' display: block;\\n';\n text += ` opacity: ${opacity};\\n`;\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ' border: 0;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += '}\\n';\n text += `#${widgetID} label > span:active img, #${widgetID} label > span:active canvas {\\n`;\n text += ' opacity: 1;\\n';\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label > span {\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label > span img,\\n`;\n text += `#${widgetID} input[type=\"radio\"]:checked + label > span canvas {\\n`;\n text += ' opacity: 1;\\n';\n text += '}\\n';\n text += '</style>\\n';\n\n text += `<div id=\"${widgetID}container\" >`;\n\n for (let i = 0; i < configuredPlayers.length; i++) {\n const player = configuredPlayers[i];\n text += ' <div >';\n text += ` <input type=\"radio\" id=\"${widgetID}${player.id}\" name=\"${widgetID}\" value=\"${player.id}\" ${\n player.id == defaultPlayer ? 'checked' : ''\n }>`;\n text += ` <label for=\"${widgetID}${player.id}\">`;\n text += ' <span>';\n const buttonsImage = player.image || '';\n if (buttonsImage.trim() != '') {\n text += ` <img src=\"${buttonsImage}\">`;\n }\n text += ' </span>';\n text += ' </label>';\n text += ' </div>';\n }\n text += '</div>';\n\n $(`#${widgetID}`).html(text);\n\n const spans = $(`#${widgetID} span`);\n const opt = {};\n opt.wrapCamelCase = data.wrapcamelcase;\n opt.style = {\n color: foregroundColor,\n direction: computedStyle.direction,\n textAlign: computedStyle.textAlign || 'center',\n };\n opt.backgroundcolor = backgroundColor;\n for (let i = 0; i < configuredPlayers.length; i++) {\n const font = new Font($(`#${widgetID}`));\n const buttonsImage = configuredPlayers[i].image || '';\n const buttonsText = configuredPlayers[i].text || configuredPlayers[i].id;\n if (buttonsImage.trim() == '') {\n $(spans[i]).append(createTextImage(buttonsText, font, picWidth, picHeight, opt));\n }\n }\n }\n $(`#${widgetID}`)\n .off('change.playerselection')\n .on('change.playerselection', () => vis.binds.squeezeboxrpc.publishPlayerSelection(widgetID));\n vis.binds.squeezeboxrpc.publishPlayerSelection(widgetID);\n $('body').trigger('squeezeboxrpcplayerschanged', [widgetID]);\n }.bind(this);\n\n try {\n const playerNames = await vis.binds['squeezeboxrpc'].sendToAsync(data.ainstance, 'getPlayerNames', {});\n if (!Array.isArray(playerNames)) {\n throw new TypeError(`Invalid getPlayerNames response: ${JSON.stringify(playerNames)}`);\n }\n renderPlayers(playerNames);\n } catch (error) {\n console.error(`Cannot read player names for ${data.ainstance}:`, error);\n $div.html('Cannot read players');\n }\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonplay = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonplay.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.state`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n this.setState(fdata);\n },\n onClick: function (event) {\n const data = event.data.data;\n const widgetID = event.data.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.state`;\n let state = $(`input[name=${widgetID}]`).val();\n state = state == 1 ? 0 : 1;\n vis.setValue(stateid, state);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const svg = vis.binds['squeezeboxrpc'].svg;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonplay.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.state`;\n\n const state =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0\n ? parseInt(vis.states[`${stateid}.val`])\n : 2;\n const imagepause = data.imagepause || '';\n const imageplay = data.imageplay || '';\n const imagestop = data.imagepause || '';\n\n let image = '';\n //0=pause\n //1=play\n //2=stop\n if (state == 0) {\n image = imageplay || svg.play;\n }\n if (state == 1) {\n image = imagepause || svg.pause;\n }\n if (state == 2) {\n image = imagestop || svg.play;\n }\n $(`#${widgetID} input`).val(state);\n $(`#${widgetID} img`).off('click.play', this.onClick);\n $(`#${widgetID} svg`).off('click.play', this.onClick);\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n $(`#${widgetID} img`).on('click.play', fdata, this.onClick);\n $(`#${widgetID} svg`).on('click.play', fdata, this.onClick);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonfwd = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonfwd.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const svg = vis.binds['squeezeboxrpc'].svg;\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"fwd\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n\n const image = data.imagefwd || svg.fwd;\n\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n\n //one onclick on span?\n $(`#${widgetID} img`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n $(`#${widgetID} svg`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.btnForward`;\n const state = true;\n vis.setValue(stateid, state);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonrew = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonrew.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const svg = vis.binds['squeezeboxrpc'].svg;\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"rew\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n\n const image = data.imagerew || svg.rew;\n\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n\n //one onclick on span?\n $(`#${widgetID} img`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n $(`#${widgetID} svg`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.btnRewind`;\n const state = true;\n vis.setValue(stateid, state);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\n/**\n * Normalize PlaylistRepeat to one of the three supported states.\n *\n * @param {string|number|undefined|null} value State value.\n */\nexport function normalizeRepeatState(value) {\n const state = Number.parseInt(String(value), 10);\n return state === 0 || state === 1 || state === 2 ? state : 0;\n}\n\n/**\n * Return the next PlaylistRepeat state.\n *\n * @param {string|number|undefined|null} value Current state value.\n */\nexport function nextRepeatState(value) {\n return (normalizeRepeatState(value) + 1) % 3;\n}\n\nexport const buttonrepeat = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonrepeat.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.PlaylistRepeat`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n this.setState({ self: this, widgetID: widgetID, view: view, data: data, style: style });\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return;\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistRepeat`;\n const state = vis.states[`${stateid}.val`];\n vis.setValue(stateid, nextRepeatState(state));\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const svg = vis.binds['squeezeboxrpc'].svg;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonrepeat.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistRepeat`;\n\n const state = normalizeRepeatState(vis.states[`${stateid}.val`]);\n const imagerepeat0 = data.imagerepeat0 || '';\n const imagerepeat1 = data.imagerepeat1 || '';\n const imagerepeat2 = data.imagerepeat2 || '';\n\n // 0 = repeat0 disabled, 1 = repeat1 enabled, 2 = custom repeat2 or repeat0 enabled\n const image =\n state === 1\n ? imagerepeat1 || svg.repeat1\n : state === 2\n ? imagerepeat2 || imagerepeat0 || svg.repeat0\n : imagerepeat0 || svg.repeat0;\n $(`#${widgetID} input`).val(state);\n $(`#${widgetID} img`).off('click.repeat', this.onClick);\n $(`#${widgetID} svg`).off('click.repeat', this.onClick);\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} span`).html(`<img src=\"${image}\">`);\n }\n $(`#${widgetID} img, #${widgetID} svg`).css('opacity', state === 0 ? '0.5' : '1');\n $(`#${widgetID} img`).on('click.repeat', fdata, this.onClick);\n $(`#${widgetID} svg`).on('click.repeat', fdata, this.onClick);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonshuffle = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonshuffle.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n let text = '';\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.PlaylistShuffle`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n this.setState({ self: this, widgetID: widgetID, view: view, data: data, style: style });\n },\n onClick: function (event) {\n const data = event.data.data;\n const widgetID = event.data.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistShuffle`;\n let state = $(`input[name=${widgetID}]`).val();\n state = state > 1 ? 0 : parseInt(state) + 1;\n vis.setValue(stateid, state);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const svg = vis.binds['squeezeboxrpc'].svg;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonshuffle.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistShuffle`;\n\n const state =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0\n ? parseInt(vis.states[`${stateid}.val`])\n : 0;\n const imageshuffle0 = data.imageshuffle0 || '';\n const imageshuffle1 = data.imageshuffle1 || '';\n const imageshuffle2 = data.imageshuffle2 || '';\n\n let image = '';\n //0=pause\n //1=play\n //2=stop\n if (state == 0) {\n image = imageshuffle0 || svg.shuffle0;\n }\n if (state == 1) {\n image = imageshuffle1 || svg.shuffle0;\n }\n if (state == 2) {\n image = imageshuffle2 || svg.shuffle2;\n }\n $(`#${widgetID} input`).val(state);\n $(`#${widgetID} img`).off('click.shuffle', this.onClick);\n $(`#${widgetID} svg`).off('click.shuffle', this.onClick);\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n if (state === 0) {\n $g.attr('opacity', '.5');\n } else {\n $g.attr('opacity', '1');\n }\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n $(`#${widgetID} img`).on('click.shuffle', fdata, this.onClick);\n $(`#${widgetID} svg`).on('click.shuffle', fdata, this.onClick);\n },\n};\n", "'use strict';\n\n/**\n * Convert a click position into an ioBroker volume value.\n *\n * @param {number} position Click position inside the bar.\n * @param {number} size Width or height of the bar.\n * @param {number} segments Number of displayed segments.\n * @param {string} calctype Calculation mode.\n * @param {boolean} reverse Whether the direction is reversed.\n * @returns {number} Volume between 0 and 100.\n */\nexport function calculateVolume(position, size, segments, calctype, reverse) {\n const safeSize = Number(size);\n const safeSegments = Math.max(2, Number.parseInt(segments, 10) || 2);\n if (!Number.isFinite(safeSize) || safeSize <= 0) {\n return 0;\n }\n\n let safePosition = Math.min(Math.max(Number(position) || 0, 0), safeSize);\n if (reverse) {\n safePosition = safeSize - safePosition;\n }\n\n if (calctype === 'exact') {\n return Math.round((safePosition / safeSize) * 100);\n }\n\n const segment = Math.min(Math.floor(safePosition / (safeSize / safeSegments)), safeSegments - 1);\n return Math.round((segment / (safeSegments - 1)) * 100);\n}\n\n/**\n * Calculate how many segments should be active for a volume value.\n *\n * @param {number} volume Volume between 0 and 100.\n * @param {number} segments Number of displayed segments.\n * @returns {number} Number of active segments.\n */\nexport function calculateActiveLevels(volume, segments) {\n const safeSegments = Math.max(2, Number.parseInt(segments, 10) || 2);\n const safeVolume = Math.min(Math.max(Number(volume) || 0, 0), 100);\n return Math.round(safeVolume / (100 / (safeSegments - 1))) + 1;\n}\n", "/* globals $,vis */\n'use strict';\n\nimport { calculateActiveLevels, calculateVolume } from '../volumeUtils.js';\n\nexport const volumebar = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].volumebar.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = {\n self: this,\n widgetID: widgetID,\n view: view,\n data: data,\n style: style,\n ainstance: ainstance,\n };\n //if ($('#' + data.widgetPlayer).length>0) this.playersChanged({data:fdata});\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.Volume`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n const calctype = data.calctype || 'segstep';\n const segments = data.segments || 11;\n const position = data.position || 'vertical';\n let segheight, segwidth;\n if (position == 'vertical') {\n segheight = data.segheight || '100%';\n segwidth = data.segwidth || '100%';\n } else {\n segheight = data.segheight || '100%';\n segwidth = data.segwidth || '20px';\n }\n const borderwidth = data.borderwidth || '1px';\n const bordercolornormal = data.bordercolornormal || '#909090';\n const bordercoloractive = data.bordercoloractive || '#87ceeb';\n const fillcolornormal = data.fillcolornormal || '#005000';\n const fillcoloractive = data.fillcoloractive || '#00ff00';\n const reverse = data.reverse || false;\n const margin = data.margin || '1px';\n\n data.calctype = calctype;\n data.segments = segments;\n data.position = position;\n\n data.segheight = segheight;\n data.segwidth = segwidth;\n data.borderwidth = borderwidth;\n data.bordercolornormal = bordercolornormal;\n data.bordercoloractive = bordercoloractive;\n data.fillcolornormal = fillcolornormal;\n data.fillcoloractive = fillcoloractive;\n data.reverse = reverse;\n data.margin = margin;\n\n let text = '';\n text += '<style> \\n';\n text += ` #${widgetID} .volume { \\n`;\n text += ' box-sizing: border-box; \\n';\n text += ' display: inline-block; \\n';\n text += ' font-size:0px; \\n';\n text += ' width: 100%; \\n';\n text += ' height: 100%; \\n';\n text += ' overflow: visible; \\n';\n if (position == 'horizontal') {\n text += ' white-space: nowrap; \\n';\n }\n text += ' } \\n';\n text += ` #${widgetID} .level { \\n`;\n text += ' box-sizing: border-box; \\n';\n text += ' display: inline-block; \\n';\n text += ` outline: ${borderwidth} solid ${bordercolornormal}; \\n`;\n if (position == 'horizontal') {\n text += ` height: calc(100% - ( 2 * ${margin} )); \\n`;\n text += ` width: calc((100% / ${segments}) - ( 2 * ${margin} )); \\n`;\n }\n if (position == 'vertical') {\n text += ` height: calc((100% / ${segments}) - ( 2 * ${margin} )); \\n`;\n text += ` width: calc(100% - ( 2 * ${margin} )); \\n`;\n }\n text += ` background-color: ${fillcolornormal}; \\n`;\n text += ` margin: ${margin}; \\n`;\n text += ' } \\n';\n text += ` #${widgetID} .active { \\n`;\n text += ` border-color: ${bordercoloractive}; \\n`;\n text += ` background-color: ${fillcoloractive}; \\n`;\n text += ' } \\n';\n text += '</style> \\n';\n\n text += '<div class=\"volume\"> \\n';\n for (let i = 0; i < segments; i++) {\n text += ` <div class=\"level\" value=\"${i}\"></div> \\n`;\n }\n text += '</div> \\n';\n $(`#${widgetID}`).html(text);\n $(`#${widgetID} div.volume`).off('click.volume').on('click.volume', fdata, this.onClick);\n this.setState(fdata);\n if (vis.editMode) {\n vis.inspectWidgets(view, view);\n }\n },\n onClick: function (event) {\n const offset = $(this).offset();\n const x = event.pageX - offset.left;\n const y = event.pageY - offset.top;\n\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.Volume`;\n\n const position = data.position == 'horizontal' ? x : y;\n const size = data.position == 'horizontal' ? this.clientWidth : this.clientHeight;\n const state = calculateVolume(position, size, data.segments, data.calctype, data.reverse);\n\n vis.binds['squeezeboxrpc'].volumebar.renderState(event.data, state);\n vis.setValue(stateid, state);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].volumebar.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.Volume`;\n let state =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0 ? vis.states[`${stateid}.val`] : 0;\n if (vis.editMode) {\n state = 50;\n }\n\n this.renderState(fdata, state);\n },\n renderState: function (fdata, state) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const reverse = data.reverse;\n const level = calculateActiveLevels(state, data.segments);\n const selector = reverse\n ? `#${widgetID} div.volume > div.level:nth-last-child(-n+${level})`\n : `#${widgetID} div.volume > div.level:nth-child(-n+${level})`;\n $(`#${widgetID} div.volume > div.level`).removeClass('active');\n $(selector).addClass('active');\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const syncgroup = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function (fdata) {\n const data = fdata.data;\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.PlayerID`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.SyncMaster`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.SyncSlaves`);\n }\n return boundstates;\n },\n function () {\n setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.createWidget(widgetID, view, data, style);\n }, 100);\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n if (vis.binds['squeezeboxrpc'].getPlayerWidgetType(view, data.widgetPlayer) == 'formatselect') {\n $div.html('Only Player formattype button is supported');\n return false;\n }\n\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n\n const dataplayer = vis.binds.squeezeboxrpc.getPlayerWidgetData(data.widgetPlayer);\n\n const picWidth = dataplayer.picWidth;\n const picHeight = dataplayer.picHeight;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercolornogroup = data.bordercolornogroup;\n const bordercolorowngroup = data.bordercolorowngroup;\n const bordercolorothergroup = data.bordercolorothergroup;\n const borderradius = data.borderradius;\n const buttonmargin = data.buttonmargin || '0px';\n\n let text = '';\n text += '<style>\\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += '}\\n';\n text += `#${widgetID} div div {\\n`;\n text += ' position: relative; \\n';\n text += ` margin: 0px ${buttonmargin} ${buttonmargin} 0px; \\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"checkbox\"] {\\n`;\n text += ' display: none;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span {\\n`;\n text += ' display: inline-block;\\n';\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornogroup};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += ' overflow: hidden;\\n';\n text += ' vertical-align: top;\\n';\n text += '}\\n';\n text += `#${widgetID} canvas {\\n`;\n text += ' display: block;\\n';\n text += ' opacity: 1;\\n';\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ' border: 0;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolorowngroup};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"checkbox\"]:checked + label > span {\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolorowngroup};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"checkbox\"][othergroup=\"true\"] + label > span {\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolorothergroup};\\n`;\n text += '}\\n';\n text += '</style>\\n';\n\n text += `<div id=\"${widgetID}container\" >`;\n let valid = false;\n for (let i = 0; i < players.length; i++) {\n const stateid = `${data.ainstance.join('.')}.Players` + `.${players[i]}.PlayerID`;\n const playerid =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0 ? vis.states[`${stateid}.val`] : '';\n valid = valid || playerid;\n text += ' <div>';\n text += ` <input type=\"checkbox\" id=\"${widgetID}${players[i]}\" name=\"${widgetID}\" playername=\"${\n players[i]\n }\" value=\"${playerid}\" disabled>`;\n text += ` <label for=\"${widgetID}${players[i]}\">`;\n text += ' <span>';\n text += ' <canvas></canvas>';\n text += ' </span>';\n text += ' </label>';\n text += ' </div>';\n }\n if (!valid) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.createWidget(widgetID, view, data, style);\n }, 100);\n }\n text += '</div>';\n $(`#${widgetID}`).html(text);\n\n for (let i = 0; i < players.length; i++) {\n const source = $(`#${data.widgetPlayer} input[value=\"${players[i]}\"] + label span :first-child`)[0];\n const destination = $(`#${widgetID}${players[i]} + label span canvas`)[0];\n if (!source || !destination) {\n continue;\n }\n\n const drawPlayerImage = function () {\n const isCanvas = source.tagName == 'CANVAS';\n const width = isCanvas ? source.width : $(source).width() || source.naturalWidth || source.width;\n const height = isCanvas ? source.height : $(source).height() || source.naturalHeight || source.height;\n if (!width || !height) {\n return;\n }\n destination.width = width;\n destination.height = height;\n const context = destination.getContext('2d');\n if (isCanvas) {\n context.drawImage(source, 0, 0);\n } else {\n context.drawImage(source, 0, 0, width, height);\n }\n };\n\n if (source.tagName == 'IMG' && !source.complete) {\n $(source).one('load.syncgroup', drawPlayerImage);\n } else {\n drawPlayerImage();\n }\n }\n\n const syncgroupbtns = $(`input[name=${widgetID}]`);\n syncgroupbtns.off('change.syncgroup').on('change.syncgroup', fdata, function (event) {\n const fdata = event.data;\n const data = fdata.data;\n const self = fdata.self;\n const syncplayer = this.value;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const syncplayername = $(this).attr('playername');\n let stateid;\n if (syncplayer) {\n if (!$(this).prop('checked')) {\n stateid = `${ainstance[0]}.${ainstance[1]}.Players` + `.${syncplayername}.cmdGeneral`;\n vis.setValue(stateid, '\"sync\",\"-\"');\n } else {\n stateid = `${ainstance[0]}.${ainstance[1]}.Players` + `.${playername}.cmdGeneral`;\n vis.setValue(stateid, `\"sync\",\"${syncplayer}\"`);\n }\n }\n self.setState(fdata);\n });\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n const syncgroups = [];\n for (let ip = 0; ip < players.length; ip++) {\n const playername = players[ip];\n const stateid1 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncMaster`;\n const stateid2 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncSlaves`;\n const state1 =\n vis.states[`${stateid1}.val`] || vis.states[`${stateid1}.val`] === 0\n ? vis.states[`${stateid1}.val`]\n : '';\n const state2 =\n vis.states[`${stateid2}.val`] || vis.states[`${stateid2}.val`] === 0\n ? vis.states[`${stateid2}.val`]\n : '';\n let state = state1.split(',').concat(state2.split(','));\n state = state.filter(item => item != '');\n if (Array.isArray(state)) {\n if (\n !syncgroups.reduce(function (acc, val) {\n return state[0] == '' || state.length == 0 || acc || val.includes(state[0]);\n }, false)\n ) {\n syncgroups.push(state);\n }\n }\n }\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.setState(fdata);\n }, 100);\n }\n const stateid1 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncMaster`;\n const stateid2 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncSlaves`;\n const stateid3 = `${data.ainstance.join('.')}.Players` + `.${playername}.PlayerID`;\n const state1 =\n vis.states[`${stateid1}.val`] || vis.states[`${stateid1}.val`] === 0 ? vis.states[`${stateid1}.val`] : '';\n const state2 =\n vis.states[`${stateid2}.val`] || vis.states[`${stateid2}.val`] === 0 ? vis.states[`${stateid2}.val`] : '';\n const state3 =\n vis.states[`${stateid3}.val`] || vis.states[`${stateid3}.val`] === 0 ? vis.states[`${stateid3}.val`] : '';\n let owngroup = null;\n for (let i = 0; i < syncgroups.length; i++) {\n if (syncgroups[i].includes(state3)) {\n owngroup = i;\n break;\n }\n }\n let state = state1.split(',').concat(state2.split(','));\n state = state.filter(item => item != '');\n for (let ip = 0; ip < players.length; ip++) {\n const playerbutton = players[ip];\n const playerstateid = `${data.ainstance.join('.')}.Players` + `.${playerbutton}.PlayerID`;\n const playerid =\n vis.states[`${playerstateid}.val`] || vis.states[`${playerstateid}.val`] === 0\n ? vis.states[`${playerstateid}.val`]\n : '';\n let playergroup = null;\n for (let is = 0; is < syncgroups.length; is++) {\n if (syncgroups[is].includes(playerid)) {\n playergroup = is;\n break;\n }\n }\n\n const $btn = $(`input[id=${widgetID}${playerbutton}]`);\n if (state.includes(playerid) && playerid !== state3) {\n $btn.prop('checked', true);\n } else {\n $btn.prop('checked', false);\n }\n if (playerid == state3) {\n $btn.prop('disabled', true);\n } else {\n $btn.prop('disabled', false);\n }\n if (playergroup != null && playergroup != owngroup) {\n $btn.attr('othergroup', true);\n } else {\n $btn.attr('othergroup', false);\n }\n }\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const playtime = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playtime.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.Duration`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.Time`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.state`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.cmdGoTime`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n const mainbarcolor = data.mainbarcolor;\n const playtimebarcolor = data.playtimebarcolor;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercolor = data.bordercolor;\n const borderradius = data.borderradius;\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} .playtimemain {\\n`;\n text += ' width: 100%;\\n';\n text += ' height: 100%;\\n';\n text += ` background-color: ${mainbarcolor};\\n`;\n text += ` border: ${bordercolor} ${borderwidth} ${borderstyle};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += ' overflow: hidden;\\n';\n text += '}';\n\n text += `#${widgetID} .playtimebar {\\n`;\n text += ' height: 100%;\\n';\n text += ` background-color: ${playtimebarcolor};\\n`;\n text += '}\\n';\n text += '</style> \\n';\n\n text += '<div class=\"playtimemain\">\\n';\n text += ' <div class=\"playtimebar\"></div>\\n';\n text += '</div>\\n';\n\n $(`#${widgetID}`).html(text);\n $(`#${widgetID} div.playtimemain`).on('click.playtime', fdata, this.onClick);\n\n this.setState(fdata);\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid_duration = `${data.ainstance.join('.')}.Players` + `.${playername}.Duration`;\n const stateid_gotime = `${data.ainstance.join('.')}.Players` + `.${playername}.cmdGoTime`;\n\n const state_duration =\n vis.states[`${stateid_duration}.val`] || vis.states[`${stateid_duration}.val`] === 0\n ? parseInt(vis.states[`${stateid_duration}.val`])\n : 0;\n const clickx = event.offsetX;\n const width = $(this).width();\n\n const time = (clickx / width) * state_duration;\n if (time > state_duration) {\n return;\n }\n vis.setValue(stateid_gotime, time.toString());\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playtime.setState(fdata);\n }, 100);\n }\n const stateid_duration = `${data.ainstance.join('.')}.Players` + `.${playername}.Duration`;\n const stateid_state = `${data.ainstance.join('.')}.Players` + `.${playername}.state`;\n const stateid_time = `${data.ainstance.join('.')}.Players` + `.${playername}.Time`;\n\n const state_duration =\n vis.states[`${stateid_duration}.val`] || vis.states[`${stateid_duration}.val`] === 0\n ? parseInt(vis.states[`${stateid_duration}.val`])\n : 0;\n const state_state =\n vis.states[`${stateid_state}.val`] || vis.states[`${stateid_state}.val`] === 0\n ? parseInt(vis.states[`${stateid_state}.val`])\n : 0;\n const state_time =\n vis.states[`${stateid_time}.val`] || vis.states[`${stateid_time}.val`] === 0\n ? parseInt(vis.states[`${stateid_time}.val`])\n : 0;\n\n let width = state_duration == 0 ? 0 : $(`#${widgetID} div.playtimebar`).width();\n if (state_state == 2) {\n width = 0;\n } //0 if player stop\n if (vis.editMode) {\n width = 50;\n } else if (state_duration <= 0) {\n width = 0;\n } else {\n width = Math.floor((state_time / state_duration) * 100);\n }\n $(`#${widgetID} div.playtimebar`).width(`${width}%`);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const string = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].string.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].string.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n const state = vis.states[`${stateid}.val`] ? vis.states[`${stateid}.val`] : '';\n //if (vis.editMode) state = data.test_html || \"\";\n const html_prepend = data.html_prepend || '';\n const html_append = data.html_append || '';\n $(`#${widgetID}`).html(html_prepend + state + html_append);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const playlist = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playlist.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: async function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const $div = $(`#${widgetID}`);\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playlist.setState(fdata);\n }, 100);\n }\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n let result = await vis.binds['squeezeboxrpc'].getPlaylistData(ainstance.join('.'));\n let playlist = result.result.playlists_loop;\n let text = '';\n text += `\n <style>\n #${widgetID} ul.plcontainer {\n list-style-type: none;\n padding-left: 0px;\n margin: 0px;\n }\n #${widgetID} li.plentry {\n cursor: pointer;\n height: 1em;\n margin: 5px 0px;\n }\n #${widgetID} li.plentry div {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n #${widgetID} li.plrefresh {\n width: 1em;\n height: 1em;\n margin: 5px 0px;\n }\n </style>\n `;\n text += '<ul class=\"plcontainer\">';\n text +=\n '<li class=\"plrefresh\"><div><svg focusable=\"false\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" data-testid=\"RefreshIcon\"><path fill=\"currentColor\" d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4z\"></path></svg></div></li>';\n for (let i = 0; i < playlist.length; i++) {\n let pl = playlist[i];\n text += `<li class=\"plentry\"><div class=\"pltext\" data-plid=\"${pl.id}\" data-pln=\"${playername}\" data-ins=\"${ainstance.join('.')}\" onclick=\"vis.binds.squeezeboxrpc.playlist.onclickplaylist(this,event)\">${pl.playlist}</div></li>`;\n }\n text += '</ul>';\n $(`#${widgetID}`).html(text);\n $(`#${widgetID} li.refresh`).click(\n function (fdata) {\n vis.binds.squeezeboxrpc.playlist.setState(fdata);\n }.bind(this, fdata),\n );\n },\n onclickplaylist: function (el) {\n const playlistid = el.dataset.plid || '';\n const playername = el.dataset.pln || '';\n const instance = el.dataset.ins || '';\n const stateid = `${instance}.Players` + `.${playername}.cmdGeneral`;\n vis.setValue(stateid, `\"playlistcontrol\",\"cmd:load\",\"playlist_id:${playlistid}\"`);\n },\n onclickrefresh: function (el) {\n const playlistid = el.dataset.plid || '';\n const playername = el.dataset.pln || '';\n const instance = el.dataset.ins || '';\n const stateid = `${instance}.Players` + `.${playername}.cmdGeneral`;\n vis.setValue(stateid, `\"playlistcontrol\",\"cmd:load\",\"playlist_id:${playlistid}\"`);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\n/**\n * Normalize the Playlist state value for rendering.\n *\n * @param {unknown} value Playlist state value\n */\nexport function parsePlaylistDetail(value) {\n let entries = value;\n if (typeof value === 'string') {\n try {\n entries = JSON.parse(value);\n } catch {\n return [];\n }\n }\n if (!Array.isArray(entries)) {\n return [];\n }\n return entries.map((entry, position) => ({\n index: Number.isInteger(Number(entry?.index)) ? Number(entry.index) : position,\n id: String(entry?.id ?? position),\n title: String(entry?.title || ''),\n artworkUrl: String(entry?.ArtworkUrl || ''),\n artist: String(entry?.Artist || ''),\n album: String(entry?.Album || ''),\n duration: Number(entry?.Duration),\n }));\n}\n\n/**\n * Format a track duration like the VIS-2 widget.\n *\n * @param {unknown} value Duration in seconds\n */\nexport function formatPlaylistDuration(value) {\n const seconds = Number(value);\n if (!Number.isFinite(seconds) || seconds < 0) {\n return '--:--';\n }\n const totalSeconds = Math.floor(seconds);\n if (totalSeconds > 99 * 3600 + 59 * 60 + 59) {\n return '>99:59:59';\n }\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const remainingSeconds = totalSeconds % 60;\n const pad = number => String(number).padStart(2, '0');\n return hours\n ? `${pad(hours)}:${pad(minutes)}:${pad(remainingSeconds)}`\n : `${pad(minutes)}:${pad(remainingSeconds)}`;\n}\n\nfunction escapeHtml(value) {\n return String(value)\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\n\nfunction cssLength(value, fallback) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return `${value}px`;\n }\n const text = String(value || fallback).trim();\n if (/^\\d+(?:\\.\\d+)?$/.test(text)) {\n return `${text}px`;\n }\n return /^\\d+(?:\\.\\d+)?(?:px|em|rem|%)$/.test(text) ? text : fallback;\n}\n\nexport const playlistdetail = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(\n () => vis.binds.squeezeboxrpc.playlistdetail.createWidget(widgetID, view, data, style),\n 100,\n );\n }\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n const ainstance = (data.ainstance = vis.binds.squeezeboxrpc.checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n const fdata = { self: this, widgetID, view, data, style };\n vis.binds.squeezeboxrpc.setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n () => {\n const states = [];\n for (const player of vis.binds.squeezeboxrpc.getPlayerValues(data.widgetPlayer)) {\n states.push(`${ainstance.join('.')}.Players.${player}.Playlist`);\n states.push(`${ainstance.join('.')}.Players.${player}.PlaylistCurrentIndex`);\n }\n return states;\n },\n this.setState.bind(fdata),\n );\n vis.binds.squeezeboxrpc.setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const { data, widgetID } = fdata;\n const previousScrollTop = $(`#${widgetID} .squeezeboxrpc-playlist-detail`).scrollTop() || 0;\n const player = vis.binds.squeezeboxrpc.getPlayerName(data.widgetPlayer);\n if (!player) {\n return setTimeout(() => vis.binds.squeezeboxrpc.playlistdetail.setState(fdata), 100);\n }\n const base = `${data.ainstance.join('.')}.Players.${player}`;\n const entries = parsePlaylistDetail(vis.states[`${base}.Playlist.val`]);\n const currentIndex = Number(vis.states[`${base}.PlaylistCurrentIndex.val`]);\n const showThumbnail = data.showThumbnail !== false && data.showThumbnail !== 'false';\n const showIndex = data.showIndex !== false && data.showIndex !== 'false';\n const rowBackground = data.rowBackground || '#f5f7fa';\n const activeBackground = data.activeRowBackground || '#dbeafe';\n const border = `${cssLength(data.rowBorderWidth, '1px')} ${data.rowBorderStyle || 'solid'} ${data.rowBorderColor || '#cbd5e1'}`;\n const spacing = cssLength(data.rowSpacing, '4px');\n let html = `<div class=\"squeezeboxrpc-playlist-detail\" style=\"--pl-row-background:${escapeHtml(rowBackground)};--pl-active-background:${escapeHtml(activeBackground)};--pl-row-border:${escapeHtml(border)};--pl-row-spacing:${escapeHtml(spacing)}\">`;\n for (const entry of entries) {\n const title = showIndex ? `${entry.index + 1}. ${entry.title}` : entry.title;\n const active = entry.index === currentIndex ? ' active' : '';\n html += `<div class=\"squeezeboxrpc-playlist-detail-row${active}${showThumbnail ? '' : ' no-thumbnail'}\">`;\n if (showThumbnail) {\n html += `<div>${entry.artworkUrl ? `<img class=\"squeezeboxrpc-playlist-detail-thumbnail\" src=\"${escapeHtml(entry.artworkUrl)}\" alt=\"\">` : ''}</div>`;\n }\n html += `<div class=\"squeezeboxrpc-playlist-detail-text\"><div class=\"squeezeboxrpc-playlist-detail-line squeezeboxrpc-playlist-detail-title\" title=\"${escapeHtml(title)}\">${escapeHtml(title)}</div><div class=\"squeezeboxrpc-playlist-detail-line\" title=\"${escapeHtml(entry.artist)}\">${escapeHtml(entry.artist)}</div><div class=\"squeezeboxrpc-playlist-detail-line\" title=\"${escapeHtml(entry.album)}\">${escapeHtml(entry.album)}</div></div>`;\n html += `<div class=\"squeezeboxrpc-playlist-detail-actions\"><span class=\"squeezeboxrpc-playlist-detail-duration\">${formatPlaylistDuration(entry.duration)}</span><div class=\"squeezeboxrpc-playlist-detail-buttons\"><button type=\"button\" class=\"squeezeboxrpc-playlist-detail-button play\" data-index=\"${entry.index}\" title=\"Play\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M8 5v14l11-7z\"/></svg></button><button type=\"button\" class=\"squeezeboxrpc-playlist-detail-button delete\" data-index=\"${entry.index}\" title=\"Delete\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM8 9h8v10H8V9zm7.5-5-1-1h-5l-1 1H5v2h14V4z\"/></svg></button></div></div></div>`;\n }\n html += '</div>';\n const $widget = $(`#${widgetID}`).html(html);\n $widget.find('.squeezeboxrpc-playlist-detail').scrollTop(previousScrollTop);\n $widget.off('.playlistdetail');\n $widget.on('click.playlistdetail', '.squeezeboxrpc-playlist-detail-button.play', event => {\n vis.setValue(`${base}.PlaylistCurrentIndex`, String(event.currentTarget.dataset.index));\n });\n $widget.on('click.playlistdetail', '.squeezeboxrpc-playlist-detail-button.delete', event => {\n vis.setValue(`${base}.cmdGeneral`, `\"playlist\",\"delete\",\"${Number(event.currentTarget.dataset.index)}\"`);\n });\n $widget.on('error.playlistdetail', '.squeezeboxrpc-playlist-detail-thumbnail', event => {\n event.currentTarget.style.visibility = 'hidden';\n });\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const number = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].number.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].number.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n let state = vis.states[`${stateid}.val`] ? vis.states[`${stateid}.val`] : '';\n // if (vis.editMode) state = data.test_html || \"\";\n state = parseFloat(state);\n if (state === undefined || state === null || isNaN(state)) {\n state = 0;\n }\n if (data.digits || data.digits !== '') {\n state = state.toFixed(parseFloat(data.digits, 10));\n }\n if (data.is_tdp && data.is_tdp !== '') {\n state = state.toString().split('.');\n state[0] = state[0].replace(/\\d{1,3}(?=(\\d{3})+(?!\\d))/g, '$&,');\n state = state.join('.');\n }\n if (data.is_comma && data.is_comma !== '') {\n state = state\n .split('.')\n .map(e => e.replace(/,/g, '.'))\n .join(',');\n }\n\n const html_prepend = data.html_prepend || '';\n const html_append = data.html_append || '';\n $(`#${widgetID}`).html(html_prepend + state + html_append);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\n/**\n * Format a player value with the same contract as the VIS-2 DateTime widget.\n *\n * @param {unknown} value Player state value\n * @param {unknown} factor Multiplier for the state value\n * @param {unknown} format Date/time format\n * @returns {string} Formatted value\n */\nexport function formatDateTime(value, factor, format) {\n const numericValue = Number(value);\n if (!Number.isFinite(numericValue)) {\n return '';\n }\n const multiplier = factor !== undefined && factor !== '' ? Number(factor) : 1;\n const offset = 60_000 * new Date(0).getTimezoneOffset();\n const date = new Date(numericValue * (Number.isFinite(multiplier) ? multiplier : 1) + offset);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n const pad = number => String(number).padStart(2, '0');\n const replacements = {\n YYYY: String(date.getFullYear()),\n YY: String(date.getFullYear()).slice(-2),\n MM: pad(date.getMonth() + 1),\n DD: pad(date.getDate()),\n hh: pad(date.getHours()),\n mm: pad(date.getMinutes()),\n ss: pad(date.getSeconds()),\n };\n return String(format || 'hh:mm:ss').replace(/YYYY|YY|MM|DD|hh|mm|ss/g, token => replacements[token]);\n}\n\nexport const datetime = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].datetime.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].datetime.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n const state = formatDateTime(vis.states[`${stateid}.val`], data.factor, data.format);\n const html_prepend = data.html_prepend || '';\n const html_append = data.html_append || '';\n $(`#${widgetID}`).html(html_prepend + state + html_append);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const image = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].image.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n let imgstyle = 'width:100%;';\n if (data.stretch) {\n imgstyle += 'height:100%;';\n }\n let text = '';\n text += data.html_prepend || '';\n text += `<img style=\"${imgstyle}\"></img> \\n`;\n text += data.html_append || '';\n $(`#${widgetID}`).html(text);\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].image.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n const state = vis.states[`${stateid}.val`] ? vis.states[`${stateid}.val`] : '';\n // if (vis.editMode) state = data.test_html || \"\";\n $(`#${widgetID} img`).attr('src', state);\n },\n};\n", "/* globals $,vis,document */\n'use strict';\n\nimport {\n legacyFavoriteConfiguration,\n legacyPlayerConfiguration,\n mergeConfiguredItems,\n moveConfiguredItem,\n parseItemConfiguration,\n serializeItemConfiguration,\n} from './itemConfiguration.js';\n\nfunction editorContext(input) {\n const wdata = $(input).data('wdata');\n const widgetID = wdata?.widgets?.[0];\n const data = widgetID && vis.views[wdata.view]?.widgets?.[widgetID]?.data;\n return data ? { data, widgetID } : null;\n}\n\nfunction playerWidgetData(widgetID) {\n if (vis.widgets?.[widgetID]?.data) {\n return vis.widgets[widgetID].data;\n }\n for (const view of Object.values(vis.views || {})) {\n if (view.widgets?.[widgetID]?.data) {\n return view.widgets[widgetID].data;\n }\n }\n return null;\n}\n\nfunction playerInstance(data) {\n const value = String(data?.ainstance || '');\n const match = value.match(/(?:system\\.adapter\\.)?(squeezeboxrpc\\.\\d+)/);\n return match ? match[1] : '';\n}\n\nfunction getStates(pattern) {\n return new Promise((resolve, reject) => {\n vis.conn.getStates(pattern, (error, states) => (error ? reject(error) : resolve(states || {})));\n });\n}\n\nasync function discover(mode, data) {\n if (mode == 'players') {\n const instance = playerInstance(data);\n if (!instance) {\n throw new Error('Please select an instance first');\n }\n const names = await vis.binds['squeezeboxrpc'].sendToAsync(instance, 'getPlayerNames', {});\n if (!Array.isArray(names)) {\n throw new TypeError('Invalid getPlayerNames response');\n }\n return names.map(id => ({ id }));\n }\n\n const referencedPlayer = playerWidgetData(data.widgetPlayer);\n const instance = playerInstance(referencedPlayer);\n if (!instance) {\n throw new Error('Please select a Players widget first');\n }\n const states = await getStates(`${instance}.Favorites.*`);\n return vis.binds['squeezeboxrpc'].favorites\n .filterFavorites(vis.binds['squeezeboxrpc'].favorites.getFavorites(states, instance.split('.')))\n .map(favorite => ({\n id: favorite.id,\n name: favorite.Name || favorite.name || '',\n image: favorite.image || '',\n }));\n}\n\nfunction makeButton(text, title, action, disabled) {\n return $('<button type=\"button\"></button>')\n .text(text)\n .attr('title', title)\n .attr('data-action', action)\n .prop('disabled', disabled);\n}\n\nfunction selectImage(state, index) {\n const item = state.items[index];\n if (!item || !$.fm) {\n return;\n }\n const defaultPath = `/${vis.conn.namespace ? `${vis.conn.namespace}/` : ''}${vis.projectPrefix}img/`;\n $.fm(\n {\n lang: vis.language,\n defaultPath,\n path: item.image || defaultPath,\n uploadDir: `/${vis.conn.namespace ? `${vis.conn.namespace}/` : ''}`,\n fileFilter: ['gif', 'png', 'bmp', 'jpg', 'jpeg', 'tif', 'svg'],\n folderFilter: false,\n mode: 'open',\n view: 'prev',\n conn: vis.conn,\n zindex: 1001,\n },\n selected => {\n item.image = selected.path + selected.file;\n renderEditor(state);\n },\n );\n}\n\nfunction renderEditor(state) {\n const $editor = state.editor.empty();\n const $toolbar = $('<div style=\"display:flex;gap:4px;margin-bottom:6px\"></div>');\n $toolbar.append(makeButton('Refresh', 'Reload available entries', 'refresh', false));\n $toolbar.append(makeButton('Apply', 'Save this configuration', 'apply', false));\n $editor.append($toolbar);\n\n if (state.message) {\n $editor.append($('<div style=\"margin:4px 0;color:#b26a00\"></div>').text(state.message));\n }\n\n const $list = $('<div style=\"display:flex;flex-direction:column;gap:4px\"></div>');\n state.items.forEach((item, index) => {\n const $row = $(\n '<div style=\"display:grid;grid-template-columns:auto minmax(90px,1fr) auto auto;gap:4px;align-items:center;border:1px solid #aaa;padding:4px\"></div>',\n );\n const $enabled = $('<input type=\"checkbox\" data-action=\"enabled\">').prop('checked', item.enabled !== false);\n const label = item.name ? `${item.id} - ${item.name}` : item.id;\n const $name = $('<span style=\"overflow:hidden;text-overflow:ellipsis;white-space:nowrap\"></span>')\n .text(item.available === false ? `${label} (unavailable)` : label)\n .attr('title', label);\n $row.attr('data-index', index).append($enabled, $name);\n $row.append(makeButton('Up', 'Move up', 'up', index == 0));\n $row.append(makeButton('Down', 'Move down', 'down', index == state.items.length - 1));\n\n if (state.mode == 'players') {\n const $default = $('<label style=\"grid-column:1 / -1\"></label>');\n $default.append(\n $('<input type=\"radio\" name=\"squeezeboxrpc-default-player\" data-action=\"default\">').prop(\n 'checked',\n state.defaultId == item.id,\n ),\n document.createTextNode(' Default player'),\n );\n $row.append($default);\n }\n $row.append(\n $(\n '<input type=\"text\" data-action=\"text\" placeholder=\"Optional button text\" style=\"grid-column:1 / -1;width:100%;box-sizing:border-box\">',\n ).val(item.text),\n );\n $row.append(\n $(\n '<input type=\"text\" data-action=\"image\" placeholder=\"Optional image URL\" style=\"grid-column:1 / -2;width:100%;box-sizing:border-box\">',\n ).val(item.image),\n );\n $row.append(makeButton('Select', 'Select image', 'image-select', false));\n $list.append($row);\n });\n $editor.append($list);\n}\n\nasync function refreshEditor(state) {\n state.message = 'Loading...';\n renderEditor(state);\n try {\n const discovered = await discover(state.mode, state.data);\n const saved = parseItemConfiguration(state.input.value);\n const legacy =\n state.mode == 'players'\n ? legacyPlayerConfiguration(\n state.data,\n discovered.map(item => item.id),\n )\n : legacyFavoriteConfiguration(state.data, discovered);\n const configuration = saved || legacy;\n state.items = mergeConfiguredItems(configuration, discovered);\n state.defaultId = configuration.defaultId;\n if (!state.items.some(item => item.id == state.defaultId && item.enabled !== false && item.available)) {\n state.defaultId = state.items.find(item => item.enabled !== false && item.available)?.id || '';\n }\n state.message = '';\n } catch (error) {\n state.message = error.message || String(error);\n }\n renderEditor(state);\n}\n\nfunction initializeEditor(input, mode, widAttr, value) {\n input.value = typeof value == 'string' ? value : '';\n const context = editorContext(input);\n const editor = $(`#inspect_${widAttr}_editor`);\n if (!context || !editor.length) {\n return;\n }\n const state = {\n ...context,\n input,\n editor,\n mode,\n items: [],\n defaultId: '',\n message: '',\n };\n editor.off('.squeezeboxrpcConfig').on('click.squeezeboxrpcConfig', '[data-action]', event => {\n const action = $(event.currentTarget).attr('data-action');\n const index = Number($(event.currentTarget).closest('[data-index]').attr('data-index'));\n if (action == 'refresh') {\n void refreshEditor(state);\n return;\n }\n if (action == 'apply') {\n input.value = serializeItemConfiguration({ version: 1, defaultId: state.defaultId, items: state.items });\n $(input).trigger('change');\n state.message = 'Configuration saved';\n renderEditor(state);\n return;\n }\n if (action == 'up' || action == 'down') {\n state.items = moveConfiguredItem(state.items, index, action == 'up' ? -1 : 1);\n renderEditor(state);\n } else if (action == 'image-select') {\n selectImage(state, index);\n }\n });\n editor.on('change.squeezeboxrpcConfig input.squeezeboxrpcConfig', '[data-index] [data-action]', event => {\n const $target = $(event.currentTarget);\n const action = $target.attr('data-action');\n const index = Number($target.closest('[data-index]').attr('data-index'));\n const item = state.items[index];\n if (!item) {\n return;\n }\n if (action == 'enabled') {\n item.enabled = $target.prop('checked');\n if (!item.enabled && state.defaultId == item.id) {\n state.defaultId = state.items.find(entry => entry.enabled !== false && entry.available)?.id || '';\n renderEditor(state);\n }\n } else if (action == 'default') {\n state.defaultId = item.id;\n } else if (action == 'text' || action == 'image') {\n item[action] = String($target.val() || '');\n }\n });\n void refreshEditor(state);\n}\n\n/**\n * Create a VIS-1 custom editor for stable item selection and ordering.\n *\n * @param mode editor mode\n * @param widAttr widget attribute name\n */\nexport function configurationEditor(mode, widAttr) {\n return {\n input: `<input type=\"hidden\" id=\"inspect_${widAttr}\"><div id=\"inspect_${widAttr}_editor\"></div>`,\n init: function (attribute, value) {\n initializeEditor(this, mode, attribute, value);\n },\n };\n}\n", "'use strict';\n\n/**\n * Normalize an ioBroker adapter-instance object or ID.\n *\n * @param value adapter instance object or ID\n * @returns normalized SqueezeboxRPC instance ID\n */\nexport function normalizeSqueezeboxInstance(value) {\n const id = String(value?._id || value?.id || value || '').replace(/^system\\.adapter\\./, '');\n return /^squeezeboxrpc\\.\\d+$/.test(id) ? id : '';\n}\n\n/**\n * Collect unique SqueezeboxRPC instance IDs from VIS objects or an object-view response.\n *\n * @param source VIS objects, object-view result, or instance list\n * @returns sorted unique instance IDs\n */\nexport function collectSqueezeboxInstances(source) {\n const values = Array.isArray(source)\n ? source\n : Array.isArray(source?.rows)\n ? source.rows.map(row => row.value?._id || row.id)\n : Object.entries(source || {}).map(([id, value]) => value?._id || id);\n return [...new Set(values.map(normalizeSqueezeboxInstance).filter(Boolean))].sort((left, right) =>\n left.localeCompare(right, undefined, { numeric: true }),\n );\n}\n", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\".3\"><path d=\"M14 10H3v2h11zm0-4H3v2h11zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2zM3 16h7v-2H3z\"/></g></svg>\n", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM8 9h8v10H8V9zm7.5-5-1-1h-5l-1 1H5v2h14V4z\"/></svg>\n", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\">\n <g transform=\"matrix(.56122 0 0 .56122 28.082 28.081)\">\n <path d=\"m98 24h15v80h-15z\"/>\n <path transform=\"matrix(1.0892 0 0 1.1187 -4.5514 -7.5937)\" d=\"m58.834 29.054 46.333 29.892a6.0144 6.0144 90 0 1 0 10.108l-46.333 29.892a5.0797 5.0797 28.586 0 1-7.8335-4.2684v-61.355a5.0797 5.0797 151.41 0 1 7.8335-4.2684z\"/>\n <path transform=\"matrix(1.0892 0 0 1.1187 -40.551 -7.5937)\" d=\"m58.834 29.054 46.333 29.892a6.0144 6.0144 90 0 1 0 10.108l-46.333 29.892a5.0797 5.0797 28.586 0 1-7.8335-4.2684v-61.355a5.0797 5.0797 151.41 0 1 7.8335-4.2684z\"/>\n </g>\n</svg>", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\".3\"><path d=\"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z\"/></g></svg>\n", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\".3\"><path d=\"m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z\"/></g></svg>\n", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <g transform=\"matrix(2.8247 0 0 2.8247 26.631 26.631)\">\n <rect x=\"5.396\" y=\"5.396\" width=\"6.4058\" height=\"15.666\" ry=\".28773\"/>\n <rect x=\"14.656\" y=\"5.396\" width=\"6.4058\" height=\"15.666\" ry=\".28773\"/>\n </g>\n</svg>", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <path d=\"m44.069 33.703 44.77 25.915a5.8115 5.2143 0 0 1 0 8.7633l-44.77 25.915a4.9083 4.4039 0 0 1-7.5692-3.7006v-53.192a4.9083 4.4039 0 0 1 7.5692-3.7006z\"/>\n</svg>\n", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\">\n <g transform=\"matrix(3.5107 0 0 3.5106 17.557 20.769)\" fill=\"currentColor\">\n <path transform=\"scale(.26458)\" d=\"m35.473 20.621c-8.2281 0-14.852 6.6235-14.852 14.852v29.055c0 8.2281 6.6235 14.852 14.852 14.852h29.055c8.2281 0 14.852-6.6235 14.852-14.852v-29.055c0-8.2281-6.6235-14.852-14.852-14.852h-4.0195v9.6641c0 .05754-.01898.1113-.02344.16797 5.108.40503 9.1016 4.6456 9.1016 9.8613v19.371c0 5.4854-4.415 9.9004-9.9004 9.9004h-19.371c-5.4854 0-9.9004-4.415-9.9004-9.9004v-19.371c0-5.4854 4.415-9.9004 9.9004-9.9004h.21094c-.0026-.04363-.01758-.08477-.01758-.12891v-9.6641z\"/>\n <path d=\"m10.111 9.4128v-5.3598c-.0082.018122-.0021-.17387.24672-.34879.24874-.17491.65793 0 .65793 0l4.6078 2.7541s.1702.098349.16971.29612c-.000497.20056-.1784.32361-.1784.32361l-4.5991 2.7487s-.39816.13052-.65793-.063572c-.25976-.19409-.24672-.35035-.24672-.35035z\"/>\n </g>\n</svg>", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\">\n <g transform=\"matrix(1.0443 0 0 1.0443 -1.6877 -1.4835)\" fill=\"currentColor\">\n <path d=\"m49.974 39.646c-7.3148 0-13.204 5.8883-13.204 13.204v25.83c0 7.3148 5.8883 13.204 13.204 13.204h13.599c-.08826-.20751-.18232-.41241-.25351-.63029-.91692-2.8066-.32741-5.663 1.2259-8.0757h-10.267c-4.8766 0-8.8015-3.925-8.8015-8.8015v-17.221c0-4.8765 3.925-8.8015 8.8015-8.8015h.18753c-.0023-.03878-.01563-.07535-.01563-.1146v-8.5915zm22.256 0v8.5915c0 .05114-.0168.09896-.02084.14933 1.4494.11493 2.7963.58042 3.9606 1.3075v-4.2159h9.043l-.158 2.6705v.0069c.0015.72589.46222 1.7794 1.5106 3.1897.6702.90145 1.5365 1.9099 2.4413 3.0177v-1.5141c0-7.3148-5.8883-13.204-13.204-13.204zm12.825 25.264-.0069 20.56c.01981 1.0467-.14027 2.0683-.44277 3.0473 2.6983-2.4141 4.4017-5.9157 4.4017-9.8378v-3.6897c-.50056.10026-1.0682.08993-1.6687-.16321-1.3963-.58871-1.712-1.7874-1.7971-2.4604-.08511-.67302.0027-1.1974.16321-1.7259.07429-.24506.28242-3.0184-.34032-5.0927-.07819-.26036-.22043-.40039-.30907-.63724z\"/>\n <path d=\"m52.414 52.942v-18.009c-.02755.06088-.0071-.58422.829-1.172.83578-.58771 2.2107 0 2.2107 0l15.483 9.254s.57188.33046.57024.99498c-.0017.6739-.59944 1.0874-.59944 1.0874l-15.453 9.2358s-1.3378.43856-2.2107-.2136c-.87281-.65216-.829-1.1772-.829-1.1772z\"/>\n <path d=\"m82.375 48.148h-3.5496v32.228c-1.9626-.84136-4.5025-.85305-7.0078.16182-4.4884 1.82-7.1623 6.247-5.9735 9.8867 1.1895 3.6406 5.7921 5.1154 10.28 3.2955 3.812-1.5454 6.3058-4.9716 6.2447-8.1982l.006-26.357c6.1892 1.0868 6.613 9.805 5.8717 12.25-.28151.92651.2142 1.6203 1.1497 0 6.6738-11.567-7.0212-16.671-7.0212-23.266z\"/>\n </g>\n</svg>", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M17.65 6.35A7.96 7.96 0 0 0 12 4a8 8 0 1 0 7.73 10h-2.08A6 6 0 1 1 16.22 7.78L13 11h7V4z\"/></svg>\n", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\">\n <g transform=\"matrix(.56121 0 0 .56122 28.082 28.082)\">\n <path d=\"m30 24h-15v80h15z\"/>\n <path d=\"m68.467 24.908-50.468 33.439a6.5512 6.728 0 0 0 0 11.307l50.468 33.439a5.533 5.6824 0 0 0 8.5326-4.7749v-68.635a5.533 5.6824 0 0 0-8.5326-4.7749z\"/>\n <path d=\"m104.47 24.907-50.468 33.439a6.5512 6.728 0 0 0 0 11.307l50.468 33.439a5.533 5.6824 0 0 0 8.5326-4.7749v-68.635a5.533 5.6824 0 0 0-8.5326-4.7749z\"/>\n </g>\n</svg>", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <g transform=\"translate(-1 -1.5)\">\n <rect x=\"35\" y=\"35\" width=\"40\" height=\"10\"/>\n <rect x=\"55\" y=\"52\" width=\"40\" height=\"10\"/>\n <rect x=\"35\" y=\"69\" width=\"40\" height=\"10\"/>\n <rect x=\"55\" y=\"86\" width=\"40\" height=\"10\"/>\n </g>\n</svg>", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <path d=\"m34 33.5v10h40v-10h-40zm20 17v10h40v-10h-40zm-20 17v10h34.5v-3.543c0-2.1921 1.7649-3.957 3.957-3.957h1.543v-2.5h-40zm20 17v10h18.457c-2.1921 0-3.957-1.7649-3.957-3.957v-6.043h-14.5z\"/>\n\n <rect\n x=\"72.5\"\n y=\"73\"\n width=\"20\"\n height=\"20\"\n rx=\"3\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n />\n</svg>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <path\n d=\"M0 0 C15.18 0 30.36 0 46 0 C46 15.18 46 30.36 46 46 C30.82 46 15.64 46 0 46 C0 30.82 0 15.64 0 0 Z\"\n transform=\"translate(41,41)\"\n />\n</svg>", "import add from '../img/add.svg';\nimport deleteIcon from '../img/delete.svg';\nimport fwd from '../img/fwd.svg';\nimport menuback from '../img/menuback.svg';\nimport next from '../img/next.svg';\nimport pause from '../img/pause.svg';\nimport play from '../img/play.svg';\nimport repeat0 from '../img/repeat0.svg';\nimport repeat1 from '../img/repeat1.svg';\nimport refresh from '../img/refresh.svg';\nimport rew from '../img/rew.svg';\nimport shuffle0 from '../img/shuffle0.svg';\nimport shuffle2 from '../img/shuffle2.svg';\nimport stop from '../img/stop.svg';\n\nconst inlineSvg = source => source.replace(/^\\s*<\\?xml[^>]*>\\s*/i, '').trim();\n\nexport const svgIcons = {\n add: inlineSvg(add),\n delete: inlineSvg(deleteIcon),\n fwd: inlineSvg(fwd),\n menuback: inlineSvg(menuback),\n next: inlineSvg(next),\n pause: inlineSvg(pause),\n play: inlineSvg(play),\n repeat0: inlineSvg(repeat0),\n repeat1: inlineSvg(repeat1),\n refresh: inlineSvg(refresh),\n rew: inlineSvg(rew),\n shuffle0: inlineSvg(shuffle0),\n shuffle2: inlineSvg(shuffle2),\n stop: inlineSvg(stop),\n};\n", "/*\n ioBroker.vis squeezeboxrpc Widget-Set\n\n Copyright 2025 oweitman oweitman@gmx.de\n\n*/\n/* globals $,vis,systemDictionary */\n'use strict';\n\n// add translations for edit mode\nimport { version as pkgVersion } from '../../../package.json';\nimport { browser } from './widgets/browser.js';\nimport { favorites } from './widgets/favorites.js';\nimport { players } from './widgets/players.js';\nimport { buttonplay } from './widgets/buttonplay.js';\nimport { buttonfwd } from './widgets/buttonfwd.js';\nimport { buttonrew } from './widgets/buttonrew.js';\nimport { buttonrepeat } from './widgets/buttonrepeat.js';\nimport { buttonshuffle } from './widgets/buttonshuffle.js';\nimport { volumebar } from './widgets/volumebar.js';\nimport { syncgroup } from './widgets/syncgroup.js';\nimport { playtime } from './widgets/playtime.js';\nimport { string } from './widgets/string.js';\nimport { playlist } from './widgets/playlist.js';\nimport { playlistdetail } from './widgets/playlistdetail.js';\nimport { number } from './widgets/number.js';\nimport { datetime } from './widgets/datetime.js';\nimport { image } from './widgets/image.js';\nimport { configurationEditor } from './configurationEditor.js';\nimport { parseItemConfiguration } from './itemConfiguration.js';\nimport { collectSqueezeboxInstances } from './instanceSelection.js';\nimport { svgIcons } from './svgIcons.js';\n\nvar translations = require('../myi18n/translations.json');\n$.extend(true, systemDictionary, translations);\n\n/* fetch('widgets/squeezeboxrpc/myi18n/translations.json').then(async res => {\n const i18n = await res.json();\n\n $.extend(true, systemDictionary, i18n);\n}); */\n\nvis.binds['squeezeboxrpc'] = {\n version: pkgVersion,\n debug: false,\n fetchResults: false,\n playerSelections: {},\n showVersion: function () {\n if (vis.binds['squeezeboxrpc'].version) {\n console.log(`Version squeezeboxrpc: ${vis.binds['squeezeboxrpc'].version}`);\n vis.binds['squeezeboxrpc'].version = null;\n }\n },\n svg: svgIcons,\n playerattributes: [\n 'Playername',\n 'PlayerID',\n 'Connected',\n 'IP',\n 'Power',\n 'Mode',\n 'Time',\n 'Rate',\n 'SyncSlaves',\n 'SyncMaster',\n 'Volume',\n 'PlaylistRepeat',\n 'PlaylistShuffle',\n 'Remote',\n 'Playlist',\n 'PlaylistCurrentIndex',\n 'state',\n 'Duration',\n 'Bitrate',\n 'Album',\n 'ArtworkUrl',\n 'Genre',\n 'Type',\n 'Title',\n 'Artist',\n 'Albumartist',\n 'Trackartist',\n 'Band',\n 'Url',\n 'RadioName',\n ],\n playerConfigurationEditor: function (widAttr) {\n return configurationEditor('players', widAttr);\n },\n favoriteConfigurationEditor: function (widAttr) {\n return configurationEditor('favorites', widAttr);\n },\n instanceSelect: function (widAttr) {\n const inputID = `inspect_${widAttr}`;\n const optionHtml = instances =>\n ['']\n .concat(instances)\n .map(instance => `<option value=\"${instance}\">${instance}</option>`)\n .join('');\n const knownInstances = collectSqueezeboxInstances(vis.objects || {});\n\n setTimeout(() => {\n if (typeof vis.conn.getObjectView != 'function') {\n return;\n }\n vis.conn.getObjectView(\n 'system',\n 'instance',\n {\n startkey: 'system.adapter.squeezeboxrpc.',\n endkey: 'system.adapter.squeezeboxrpc.\\u9999',\n },\n (error, result) => {\n if (error) {\n console.error('Cannot read SqueezeboxRPC instances:', error);\n return;\n }\n const $select = $(`#${inputID}`);\n if (!$select.length) {\n return;\n }\n const selected = $select.val();\n const instances = collectSqueezeboxInstances(result);\n if (selected && !instances.includes(selected)) {\n instances.unshift(selected);\n }\n $select.html(optionHtml(instances)).val(selected);\n },\n );\n }, 0);\n\n return { input: `<select type=\"text\" id=\"${inputID}\">${optionHtml(knownInstances)}</select>` };\n },\n getPlayerWidgetData: function (playerWidgetID) {\n if (vis.widgets?.[playerWidgetID]?.data) {\n return vis.widgets[playerWidgetID].data;\n }\n for (const view of Object.values(vis.views || {})) {\n if (view.widgets?.[playerWidgetID]?.data) {\n return view.widgets[playerWidgetID].data;\n }\n }\n return null;\n },\n getPlayerWidgetType: function (_view, playerWidgetID) {\n return this.getPlayerWidgetData(playerWidgetID)?.formattype || '';\n },\n checkAttributes: function ($div, widgetPlayer) {\n if (!widgetPlayer) {\n $div.html('Please select a player widget');\n return false;\n }\n const playerData = this.getPlayerWidgetData(widgetPlayer);\n if (!playerData?.ainstance) {\n $div.html('Please select an instance at the playerwidget');\n return false;\n }\n const ainstance = playerData.ainstance.split('.');\n if (!ainstance || ainstance[0] != 'squeezeboxrpc') {\n $div.html('Please select an instance at the playerwidget');\n return false;\n }\n return ainstance;\n },\n setChanged: function (widgetPlayer, fdata) {\n $('body')\n .off(`squeezeboxrpcplayerchange.${fdata.widgetID}`)\n .on(`squeezeboxrpcplayerchange.${fdata.widgetID}`, fdata, function (_event, changedWidget) {\n if (changedWidget != widgetPlayer) {\n return;\n }\n const self = fdata.self;\n self.setState(fdata);\n });\n },\n setPlayersChanged: function (\n $div,\n widgetPlayer,\n fdata,\n onChange_callback,\n boundstates_callback,\n playerChanged_callback,\n ) {\n const bindPlayerStates = () => {\n const boundstates = boundstates_callback(fdata);\n if (boundstates?.length) {\n vis.binds['squeezeboxrpc'].bindStates($div, boundstates, onChange_callback, fdata);\n }\n };\n\n $('body')\n .off(`squeezeboxrpcplayerschanged.${fdata.widgetID}`)\n .on(`squeezeboxrpcplayerschanged.${fdata.widgetID}`, (_event, changedWidget) => {\n if (changedWidget != widgetPlayer) {\n return;\n }\n bindPlayerStates();\n playerChanged_callback?.(fdata);\n });\n\n bindPlayerStates();\n },\n bindStates: function (elem, bound, change_callback, fdata) {\n const $div = $(elem);\n const boundstates = $div.data('bound');\n if (boundstates) {\n for (let i = 0; i < boundstates.length; i++) {\n vis.states.unbind(boundstates[i], change_callback);\n }\n }\n $div.data('bound', null);\n $div.data('bindHandler', null);\n\n vis.conn.gettingStates = 0;\n vis.conn.getStates(\n bound,\n function (error, states) {\n if (error) {\n console.error('Cannot read initial widget states:', error);\n }\n vis.updateStates(states || {});\n vis.conn.subscribe(bound);\n for (let i = 0; i < bound.length; i++) {\n bound[i] = `${bound[i]}.val`;\n vis.states.bind(bound[i], change_callback);\n }\n $div.data('bound', bound);\n $div.data('bindHandler', change_callback);\n change_callback.call(fdata);\n }.bind({ fdata, change_callback }),\n );\n },\n attrSelect: function (wid_attr, options) {\n if (wid_attr === 'widgetPlayer') {\n options = this.findPlayerWidgets();\n }\n if (wid_attr === 'widgetFavorites') {\n options = this.findFavoritesWidgets();\n }\n let html = '';\n for (let i = 0; i < options.length; i++) {\n const value = typeof options[i] == 'string' ? options[i] : options[i].value;\n const label = typeof options[i] == 'string' ? options[i] : options[i].label;\n html += `<option value=\"${value}\">${label}</option>`;\n }\n const line = {\n input: `<select type=\"text\" id=\"inspect_${wid_attr}\">${html}</select>`,\n };\n return line;\n },\n playerAttrSelect: function (wid_attr) {\n let html = '';\n const playerattributes = vis.binds['squeezeboxrpc'].playerattributes.sort();\n for (let i = 0; i < playerattributes.length; i++) {\n html += `<option value=\"${playerattributes[i]}\">${playerattributes[i]}</option>`;\n }\n const line = {\n input: `<select type=\"text\" id=\"inspect_${wid_attr}\">${html}</select>`,\n };\n return line;\n },\n findPlayerWidgets: function () {\n const result = [];\n for (const [viewName, view] of Object.entries(vis.views || {})) {\n for (const [widgetID, widget] of Object.entries(view.widgets || {})) {\n if (widget.tpl == 'tplSqueezeboxrpcPlayer') {\n const instance = String(widget.data?.ainstance || '').replace(/^system\\.adapter\\./, '');\n const name = String(widget.data?.name || widgetID);\n result.push({\n value: widgetID,\n label: instance ? `${instance} (${viewName}: ${name})` : `${viewName}: ${name}`,\n });\n }\n }\n }\n return result.sort((left, right) => left.label.localeCompare(right.label, undefined, { numeric: true }));\n },\n findFavoritesWidgets: function () {\n const widgets = vis.views[vis.activeView].widgets;\n const keys = Object.keys(widgets);\n const result = [];\n for (let i = 0; i < keys.length; i++) {\n if (widgets[keys[i]].tpl == 'tplSqueezeboxrpcFavorites') {\n result.push(keys[i]);\n }\n }\n return result;\n },\n getPlayerValues: function (widgetPlayer) {\n const domValues = $(`input[name=${widgetPlayer}], #${widgetPlayer} option`)\n .toArray()\n .reduce(function (acc, cur) {\n if ($(cur).val()) {\n acc.push($(cur).val());\n }\n return acc;\n }, []);\n if (domValues.length) {\n return domValues;\n }\n const published = this.playerSelections[widgetPlayer]?.players;\n if (published?.length) {\n return published.slice();\n }\n const configuration = parseItemConfiguration(this.getPlayerWidgetData(widgetPlayer)?.playerConfiguration);\n return configuration ? configuration.items.filter(item => item.enabled !== false).map(item => item.id) : [];\n },\n getPlayerName: function (widgetPlayer) {\n const domValue = $(`input[name=${widgetPlayer}]:checked, #${widgetPlayer} option:checked`).val();\n if (domValue) {\n return domValue;\n }\n const published = this.playerSelections[widgetPlayer]?.player;\n if (published) {\n return published;\n }\n const configuration = parseItemConfiguration(this.getPlayerWidgetData(widgetPlayer)?.playerConfiguration);\n const players = configuration?.items.filter(item => item.enabled !== false) || [];\n return players.some(item => item.id == configuration?.defaultId) ? configuration.defaultId : players[0]?.id;\n },\n publishPlayerSelection: function (widgetPlayer) {\n const playerData = this.getPlayerWidgetData(widgetPlayer);\n const player = $(`input[name=${widgetPlayer}]:checked, #${widgetPlayer} option:checked`).val();\n const players = $(`input[name=${widgetPlayer}], #${widgetPlayer} option`)\n .toArray()\n .map(element => $(element).val())\n .filter(Boolean);\n if (!playerData?.ainstance || !player) {\n return;\n }\n this.playerSelections[widgetPlayer] = {\n instance: String(playerData.ainstance).replace(/^system\\.adapter\\./, ''),\n player,\n players,\n };\n $('body').trigger('squeezeboxrpcplayerchange', [widgetPlayer]);\n },\n getPlayerNameAsync: async function (widgetPlayer) {\n return new Promise((resolve, reject) => {\n (async () => {\n let i = 0;\n while (i < 1000) {\n let playername = this.getPlayerName(widgetPlayer);\n if (!playername) {\n await new Promise(r => setTimeout(r, 100));\n } else {\n resolve(playername);\n return;\n }\n i++;\n console.log(i);\n }\n reject();\n })();\n });\n },\n onHorizChange: function (widgetID, view, newId) {\n const data = vis.views[view].widgets[widgetID].data;\n if (newId == 'vertical') {\n data.segheight = '100%';\n data.segwidth = '100%';\n } else {\n data.segheight = '20px';\n data.segwidth = '20px';\n }\n return true;\n },\n editDimension: function (widgetID, view, newId, attr) {\n if (newId && typeof newId !== 'object') {\n const e = newId.substring(newId.length - 2);\n if (e !== 'px' && e !== 'em' && newId[newId.length - 1] !== '%') {\n vis.views[view].widgets[widgetID].data[attr] = `${newId}px`;\n }\n }\n },\n browsesendToAsync: async function (instance, command, sendData) {\n let result = await vis.binds['squeezeboxrpc'].sendToAsync(instance, command, sendData);\n if (vis.binds['squeezeboxrpc'].fetchResults) {\n console.debug('debugbrowsersendtoasync', {\n debug: 'debug data',\n instance: instance,\n command: command,\n sendData: sendData,\n result: result,\n });\n }\n return result;\n },\n sendToAsync: async function (instance, command, sendData) {\n console.log(`sendToAsync ${command} ${JSON.stringify(sendData)}`);\n return new Promise((resolve /* , reject */) => {\n // eslint-disable-next-line no-useless-catch\n try {\n vis.conn.sendTo(instance, command, sendData, function (receiveData) {\n resolve(receiveData);\n });\n } catch (error) {\n throw error;\n //reject(error);\n }\n });\n },\n getPlaylistData: async function (instance) {\n console.log(`getPlaylistData`);\n const data = {\n playerid: '',\n cmdArray: ['playlists', '0', '999', 'tags:us'],\n };\n return await this.sendToAsync(instance, 'cmdGeneral', data);\n },\n getPlayerID: async function (state) {\n console.log(`getPlayerID`);\n return new Promise((resolve, reject) => {\n try {\n vis.conn.gettingStates = 0;\n vis.conn.getStates([state], function (error, states) {\n resolve(states[state].val);\n });\n } catch (error) {\n reject(error);\n }\n });\n },\n browser,\n favorites,\n players,\n buttonplay,\n buttonfwd,\n buttonrew,\n buttonrepeat,\n buttonshuffle,\n volumebar,\n syncgroup,\n playtime,\n string,\n playlist,\n playlistdetail,\n number,\n datetime,\n image,\n};\nvis.binds['squeezeboxrpc'].showVersion();\n//function css() {} // remove tagged temlate string error message, tagging is needed to format the css code\n// function html() {} // remove tagged temlate string error message, tagging is needed to format the html code\n", "import './sbClasses.js';\nimport './squeezeboxrpc.js';\nimport './date.format.js';\nimport './textImage.js';\n"],
|
|
4
|
+
"sourcesContent": ["{\n \"ainstance\": { \"en\": \"SqueezeboxRPC instance\", \"de\": \"SqueezeboxRPC-Instanz\", \"ru\": \"\u042D\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440 SqueezeboxRPC\", \"pt\": \"Inst\u00E2ncia SqueezeboxRPC\", \"nl\": \"SqueezeboxRPC-instantie\", \"fr\": \"Instance SqueezeboxRPC\", \"it\": \"Istanza SqueezeboxRPC\", \"es\": \"Instancia SqueezeboxRPC\", \"pl\": \"Instancja SqueezeboxRPC\", \"uk\": \"\u0415\u043A\u0437\u0435\u043C\u043F\u043B\u044F\u0440 SqueezeboxRPC\", \"zh-cn\": \"SqueezeboxRPC \u5B9E\u4F8B\" },\n \"viewindex\": { \"en\": \"Viewindex\", \"de\": \"Ansichtsindex\", \"ru\": \"\u0418\u043D\u0434\u0435\u043A\u0441 \u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043B\u0435\u043D\u0438\u044F\", \"pt\": \"\u00CDndice da vista\", \"nl\": \"Weergave-index\", \"fr\": \"Index de vue\", \"it\": \"Indice vista\", \"es\": \"\u00CDndice de vista\", \"pl\": \"Indeks widoku\", \"uk\": \"\u0406\u043D\u0434\u0435\u043A\u0441 \u043F\u043E\u0434\u0430\u043D\u043D\u044F\", \"zh-cn\": \"\u89C6\u56FE\u7D22\u5F15\" },\n \"wrapcamelcase\": { \"en\": \"Wrap Camelcase\", \"de\": \"CamelCase umbrechen\", \"ru\": \"\u041F\u0435\u0440\u0435\u043D\u043E\u0441 CamelCase\", \"pt\": \"Quebrar CamelCase\", \"nl\": \"CamelCase afbreken\", \"fr\": \"Renvoyer CamelCase \u00E0 la ligne\", \"it\": \"A capo CamelCase\", \"es\": \"Dividir CamelCase\", \"pl\": \"Zawijaj CamelCase\", \"uk\": \"\u041F\u0435\u0440\u0435\u043D\u043E\u0441\u0438\u0442\u0438 CamelCase\", \"zh-cn\": \"CamelCase \u6362\u884C\" },\n \"buttonbkcolor\": { \"en\": \"Button background color\", \"de\": \"Schaltfl\u00E4chen-Hintergrundfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Cor de fundo do bot\u00E3o\", \"nl\": \"Achtergrondkleur knop\", \"fr\": \"Couleur d'arri\u00E8re-plan du bouton\", \"it\": \"Colore di sfondo del pulsante\", \"es\": \"Color de fondo del bot\u00F3n\", \"pl\": \"Kolor t\u0142a przycisku\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0444\u043E\u043D\u0443 \u043A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\u80CC\u666F\u989C\u8272\" },\n \"widgetPlayer\": { \"en\": \"Player widget\", \"de\": \"Player-Widget\", \"ru\": \"\u0412\u0438\u0434\u0436\u0435\u0442 \u043F\u0440\u043E\u0438\u0433\u0440\u044B\u0432\u0430\u0442\u0435\u043B\u044F\", \"pt\": \"Widget do leitor\", \"nl\": \"Spelerwidget\", \"fr\": \"Widget du lecteur\", \"it\": \"Widget del lettore\", \"es\": \"Widget del reproductor\", \"pl\": \"Wid\u017Cet odtwarzacza\", \"uk\": \"\u0412\u0456\u0434\u0436\u0435\u0442 \u043F\u0440\u043E\u0433\u0440\u0430\u0432\u0430\u0447\u0430\", \"zh-cn\": \"\u64AD\u653E\u5668\u5C0F\u90E8\u4EF6\" },\n \"widgetFavorites\": { \"en\": \"Favorite widget\", \"de\": \"Favoriten-Widget\", \"ru\": \"\u0412\u0438\u0434\u0436\u0435\u0442 \u0438\u0437\u0431\u0440\u0430\u043D\u043D\u043E\u0433\u043E\", \"pt\": \"Widget de favoritos\", \"nl\": \"Favorietenwidget\", \"fr\": \"Widget des favoris\", \"it\": \"Widget dei preferiti\", \"es\": \"Widget de favoritos\", \"pl\": \"Wid\u017Cet ulubionych\", \"uk\": \"\u0412\u0456\u0434\u0436\u0435\u0442 \u043E\u0431\u0440\u0430\u043D\u043E\u0433\u043E\", \"zh-cn\": \"\u6536\u85CF\u5939\u5C0F\u90E8\u4EF6\" },\n \"picHeight\": { \"en\": \"Button height\", \"de\": \"Schaltfl\u00E4chenh\u00F6he\", \"ru\": \"\u0412\u044B\u0441\u043E\u0442\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Altura do bot\u00E3o\", \"nl\": \"Knophoogte\", \"fr\": \"Hauteur du bouton\", \"it\": \"Altezza del pulsante\", \"es\": \"Altura del bot\u00F3n\", \"pl\": \"Wysoko\u015B\u0107 przycisku\", \"uk\": \"\u0412\u0438\u0441\u043E\u0442\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\u9AD8\u5EA6\" },\n \"picWidth\": { \"en\": \"Button width\", \"de\": \"Schaltfl\u00E4chenbreite\", \"ru\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Largura do bot\u00E3o\", \"nl\": \"Knopbreedte\", \"fr\": \"Largeur du bouton\", \"it\": \"Larghezza del pulsante\", \"es\": \"Anchura del bot\u00F3n\", \"pl\": \"Szeroko\u015B\u0107 przycisku\", \"uk\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\u5BBD\u5EA6\" },\n \"opacity\": { \"en\": \"Opacity\", \"de\": \"Deckkraft\", \"ru\": \"\u041D\u0435\u043F\u0440\u043E\u0437\u0440\u0430\u0447\u043D\u043E\u0441\u0442\u044C\", \"pt\": \"Opacidade\", \"nl\": \"Dekking\", \"fr\": \"Opacit\u00E9\", \"it\": \"Opacit\u00E0\", \"es\": \"Opacidad\", \"pl\": \"Krycie\", \"uk\": \"\u041D\u0435\u043F\u0440\u043E\u0437\u043E\u0440\u0456\u0441\u0442\u044C\", \"zh-cn\": \"\u4E0D\u900F\u660E\u5EA6\" },\n \"editmodehelper\": { \"en\": \"Edit Mode Helper\", \"de\": \"Bearbeitungsmodus-Hilfe\", \"ru\": \"\u041F\u043E\u043C\u043E\u0449\u043D\u0438\u043A \u0440\u0435\u0436\u0438\u043C\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\", \"pt\": \"Auxiliar do modo de edi\u00E7\u00E3o\", \"nl\": \"Hulp voor bewerkingsmodus\", \"fr\": \"Assistant du mode \u00E9dition\", \"it\": \"Assistente modalit\u00E0 modifica\", \"es\": \"Ayuda del modo de edici\u00F3n\", \"pl\": \"Pomoc trybu edycji\", \"uk\": \"\u041F\u043E\u043C\u0456\u0447\u043D\u0438\u043A \u0440\u0435\u0436\u0438\u043C\u0443 \u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043D\u043D\u044F\", \"zh-cn\": \"\u7F16\u8F91\u6A21\u5F0F\u52A9\u624B\" },\n \"group_buttonsettings\": { \"en\": \"Button options\", \"de\": \"Schaltfl\u00E4chenoptionen\", \"ru\": \"\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043A\u043D\u043E\u043F\u043E\u043A\", \"pt\": \"Op\u00E7\u00F5es dos bot\u00F5es\", \"nl\": \"Knopopties\", \"fr\": \"Options des boutons\", \"it\": \"Opzioni dei pulsanti\", \"es\": \"Opciones de botones\", \"pl\": \"Opcje przycisk\u00F3w\", \"uk\": \"\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0438 \u043A\u043D\u043E\u043F\u043E\u043A\", \"zh-cn\": \"\u6309\u94AE\u9009\u9879\" },\n \"borderwidth\": { \"en\": \"Border width\", \"de\": \"Rahmenbreite\", \"ru\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Largura da borda\", \"nl\": \"Randbreedte\", \"fr\": \"Largeur de bordure\", \"it\": \"Larghezza bordo\", \"es\": \"Anchura del borde\", \"pl\": \"Szeroko\u015B\u0107 obramowania\", \"uk\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u5BBD\u5EA6\" },\n \"borderstyle\": { \"en\": \"Border-style\", \"de\": \"Rahmenart\", \"ru\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Estilo da borda\", \"nl\": \"Randstijl\", \"fr\": \"Style de bordure\", \"it\": \"Stile bordo\", \"es\": \"Estilo del borde\", \"pl\": \"Styl obramowania\", \"uk\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u6837\u5F0F\" },\n \"bordercolornormal\": { \"en\": \"Border width normal\", \"de\": \"Rahmenfarbe normal\", \"ru\": \"\u041E\u0431\u044B\u0447\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor normal da borda\", \"nl\": \"Normale randkleur\", \"fr\": \"Couleur de bordure normale\", \"it\": \"Colore bordo normale\", \"es\": \"Color normal del borde\", \"pl\": \"Normalny kolor obramowania\", \"uk\": \"\u0417\u0432\u0438\u0447\u0430\u0439\u043D\u0438\u0439 \u043A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u666E\u901A\u8FB9\u6846\u989C\u8272\" },\n \"bordercoloractive\": { \"en\": \"Border width aktiv\", \"de\": \"Rahmenfarbe aktiv\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0439 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor da borda ativa\", \"nl\": \"Actieve randkleur\", \"fr\": \"Couleur de bordure active\", \"it\": \"Colore bordo attivo\", \"es\": \"Color del borde activo\", \"pl\": \"Kolor aktywnego obramowania\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0457 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u6D3B\u52A8\u8FB9\u6846\u989C\u8272\" },\n \"borderradius\": { \"en\": \"border-radius\", \"de\": \"Rahmenradius\", \"ru\": \"\u0420\u0430\u0434\u0438\u0443\u0441 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Raio da borda\", \"nl\": \"Randradius\", \"fr\": \"Rayon de bordure\", \"it\": \"Raggio bordo\", \"es\": \"Radio del borde\", \"pl\": \"Promie\u0144 obramowania\", \"uk\": \"\u0420\u0430\u0434\u0456\u0443\u0441 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u5706\u89D2\" },\n \"imagefwd\": { \"en\": \"Picture\", \"de\": \"Bild\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435\", \"pt\": \"Imagem\", \"nl\": \"Afbeelding\", \"fr\": \"Image\", \"it\": \"Immagine\", \"es\": \"Imagen\", \"pl\": \"Obraz\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u56FE\u7247\" },\n \"group_svgsettings\": { \"en\": \"SVG Settings\", \"de\": \"SVG-Einstellungen\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 SVG\", \"pt\": \"Defini\u00E7\u00F5es SVG\", \"nl\": \"SVG-instellingen\", \"fr\": \"Param\u00E8tres SVG\", \"it\": \"Impostazioni SVG\", \"es\": \"Ajustes SVG\", \"pl\": \"Ustawienia SVG\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F SVG\", \"zh-cn\": \"SVG \u8BBE\u7F6E\" },\n \"fillcolor\": { \"en\": \"fillcolor\", \"de\": \"F\u00FCllfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"pt\": \"Cor de preenchimento\", \"nl\": \"Vulkleur\", \"fr\": \"Couleur de remplissage\", \"it\": \"Colore riempimento\", \"es\": \"Color de relleno\", \"pl\": \"Kolor wype\u0142nienia\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"zh-cn\": \"\u586B\u5145\u989C\u8272\" },\n \"strokecolor\": { \"en\": \"strokecolor\", \"de\": \"Konturfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u043A\u043E\u043D\u0442\u0443\u0440\u0430\", \"pt\": \"Cor do contorno\", \"nl\": \"Lijnkleur\", \"fr\": \"Couleur du contour\", \"it\": \"Colore contorno\", \"es\": \"Color del trazo\", \"pl\": \"Kolor obrysu\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u043A\u043E\u043D\u0442\u0443\u0440\u0443\", \"zh-cn\": \"\u63CF\u8FB9\u989C\u8272\" },\n \"strokewidth\": { \"en\": \"strokewidth\", \"de\": \"Konturbreite\", \"ru\": \"\u0422\u043E\u043B\u0449\u0438\u043D\u0430 \u043A\u043E\u043D\u0442\u0443\u0440\u0430\", \"pt\": \"Largura do contorno\", \"nl\": \"Lijndikte\", \"fr\": \"Largeur du contour\", \"it\": \"Spessore contorno\", \"es\": \"Grosor del trazo\", \"pl\": \"Szeroko\u015B\u0107 obrysu\", \"uk\": \"\u0422\u043E\u0432\u0449\u0438\u043D\u0430 \u043A\u043E\u043D\u0442\u0443\u0440\u0443\", \"zh-cn\": \"\u63CF\u8FB9\u5BBD\u5EA6\" },\n \"imagerew\": { \"en\": \"Picture\", \"de\": \"Bild\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435\", \"pt\": \"Imagem\", \"nl\": \"Afbeelding\", \"fr\": \"Image\", \"it\": \"Immagine\", \"es\": \"Imagen\", \"pl\": \"Obraz\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u56FE\u7247\" },\n \"imagepause\": { \"en\": \"Picture pause\", \"de\": \"Bild Pause\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0430\u0443\u0437\u044B\", \"pt\": \"Imagem de pausa\", \"nl\": \"Afbeelding pauze\", \"fr\": \"Image de pause\", \"it\": \"Immagine pausa\", \"es\": \"Imagen de pausa\", \"pl\": \"Obraz pauzy\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u0430\u0443\u0437\u0438\", \"zh-cn\": \"\u6682\u505C\u56FE\u7247\" },\n \"imageplay\": { \"en\": \"Picture play\", \"de\": \"Bild Wiedergabe\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0432\u043E\u0441\u043F\u0440\u043E\u0438\u0437\u0432\u0435\u0434\u0435\u043D\u0438\u044F\", \"pt\": \"Imagem de reprodu\u00E7\u00E3o\", \"nl\": \"Afbeelding afspelen\", \"fr\": \"Image de lecture\", \"it\": \"Immagine riproduzione\", \"es\": \"Imagen de reproducci\u00F3n\", \"pl\": \"Obraz odtwarzania\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0432\u0456\u0434\u0442\u0432\u043E\u0440\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u64AD\u653E\u56FE\u7247\" },\n \"imagestop\": { \"en\": \"Picture stop\", \"de\": \"Bild Stopp\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438\", \"pt\": \"Imagem de paragem\", \"nl\": \"Afbeelding stoppen\", \"fr\": \"Image d'arr\u00EAt\", \"it\": \"Immagine arresto\", \"es\": \"Imagen de parada\", \"pl\": \"Obraz zatrzymania\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0437\u0443\u043F\u0438\u043D\u043A\u0438\", \"zh-cn\": \"\u505C\u6B62\u56FE\u7247\" },\n \"calctype\": { \"en\": \"CalcType\", \"de\": \"Berechnungsart\", \"ru\": \"\u0422\u0438\u043F \u0440\u0430\u0441\u0447\u0451\u0442\u0430\", \"pt\": \"Tipo de c\u00E1lculo\", \"nl\": \"Berekeningstype\", \"fr\": \"Type de calcul\", \"it\": \"Tipo di calcolo\", \"es\": \"Tipo de c\u00E1lculo\", \"pl\": \"Typ obliczenia\", \"uk\": \"\u0422\u0438\u043F \u043E\u0431\u0447\u0438\u0441\u043B\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u8BA1\u7B97\u7C7B\u578B\" },\n \"segments\": { \"en\": \"Segments\", \"de\": \"Segmente\", \"ru\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u044B\", \"pt\": \"Segmentos\", \"nl\": \"Segmenten\", \"fr\": \"Segments\", \"it\": \"Segmenti\", \"es\": \"Segmentos\", \"pl\": \"Segmenty\", \"uk\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u0438\", \"zh-cn\": \"\u5206\u6BB5\" },\n \"fillcolornormal\": { \"en\": \"fillcolornormal\", \"de\": \"Normale F\u00FCllfarbe\", \"ru\": \"\u041E\u0431\u044B\u0447\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"pt\": \"Cor de preenchimento normal\", \"nl\": \"Normale vulkleur\", \"fr\": \"Couleur de remplissage normale\", \"it\": \"Colore riempimento normale\", \"es\": \"Color de relleno normal\", \"pl\": \"Normalny kolor wype\u0142nienia\", \"uk\": \"\u0417\u0432\u0438\u0447\u0430\u0439\u043D\u0438\u0439 \u043A\u043E\u043B\u0456\u0440 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"zh-cn\": \"\u666E\u901A\u586B\u5145\u989C\u8272\" },\n \"fillcoloractive\": { \"en\": \"fillcoloractive\", \"de\": \"Aktive F\u00FCllfarbe\", \"ru\": \"\u0410\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0446\u0432\u0435\u0442 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"pt\": \"Cor de preenchimento ativa\", \"nl\": \"Actieve vulkleur\", \"fr\": \"Couleur de remplissage active\", \"it\": \"Colore riempimento attivo\", \"es\": \"Color de relleno activo\", \"pl\": \"Aktywny kolor wype\u0142nienia\", \"uk\": \"\u0410\u043A\u0442\u0438\u0432\u043D\u0438\u0439 \u043A\u043E\u043B\u0456\u0440 \u0437\u0430\u043B\u0438\u0432\u043A\u0438\", \"zh-cn\": \"\u6D3B\u52A8\u586B\u5145\u989C\u8272\" },\n \"position\": { \"en\": \"Format\", \"de\": \"Format\", \"ru\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"pt\": \"Formato\", \"nl\": \"Indeling\", \"fr\": \"Format\", \"it\": \"Formato\", \"es\": \"Formato\", \"pl\": \"Format\", \"uk\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"zh-cn\": \"\u683C\u5F0F\" },\n \"group_segmentsettings\": { \"en\": \"Segments\", \"de\": \"Segmente\", \"ru\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u044B\", \"pt\": \"Segmentos\", \"nl\": \"Segmenten\", \"fr\": \"Segments\", \"it\": \"Segmenti\", \"es\": \"Segmentos\", \"pl\": \"Segmenty\", \"uk\": \"\u0421\u0435\u0433\u043C\u0435\u043D\u0442\u0438\", \"zh-cn\": \"\u5206\u6BB5\" },\n \"margin\": { \"en\": \"margin\", \"de\": \"Abstand\", \"ru\": \"\u041E\u0442\u0441\u0442\u0443\u043F\", \"pt\": \"Margem\", \"nl\": \"Marge\", \"fr\": \"Marge\", \"it\": \"Margine\", \"es\": \"Margen\", \"pl\": \"Margines\", \"uk\": \"\u0412\u0456\u0434\u0441\u0442\u0443\u043F\", \"zh-cn\": \"\u5916\u8FB9\u8DDD\" },\n \"imagerepeat0\": { \"en\": \"Picture without\", \"de\": \"Bild ohne Wiederholung\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0431\u0435\u0437 \u043F\u043E\u0432\u0442\u043E\u0440\u0430\", \"pt\": \"Imagem sem repeti\u00E7\u00E3o\", \"nl\": \"Afbeelding zonder herhaling\", \"fr\": \"Image sans r\u00E9p\u00E9tition\", \"it\": \"Immagine senza ripetizione\", \"es\": \"Imagen sin repetici\u00F3n\", \"pl\": \"Obraz bez powtarzania\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0431\u0435\u0437 \u043F\u043E\u0432\u0442\u043E\u0440\u0443\", \"zh-cn\": \"\u4E0D\u91CD\u590D\u56FE\u7247\" },\n \"imagerepeat1\": { \"en\": \"Picture Title\", \"de\": \"Bild Titel wiederholen\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u0430 \u0442\u0440\u0435\u043A\u0430\", \"pt\": \"Imagem de repeti\u00E7\u00E3o da faixa\", \"nl\": \"Afbeelding titel herhalen\", \"fr\": \"Image de r\u00E9p\u00E9tition du titre\", \"it\": \"Immagine ripeti titolo\", \"es\": \"Imagen de repetir t\u00EDtulo\", \"pl\": \"Obraz powtarzania utworu\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0443 \u0442\u0440\u0435\u043A\u0443\", \"zh-cn\": \"\u91CD\u590D\u66F2\u76EE\u56FE\u7247\" },\n \"imagerepeat2\": { \"en\": \"Picture Playlist\", \"de\": \"Bild Playlist wiederholen\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u0430 \u043F\u043B\u0435\u0439\u043B\u0438\u0441\u0442\u0430\", \"pt\": \"Imagem de repeti\u00E7\u00E3o da lista\", \"nl\": \"Afbeelding afspeellijst herhalen\", \"fr\": \"Image de r\u00E9p\u00E9tition de la playlist\", \"it\": \"Immagine ripeti playlist\", \"es\": \"Imagen de repetir lista\", \"pl\": \"Obraz powtarzania playlisty\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u043E\u0432\u0442\u043E\u0440\u0443 \u0441\u043F\u0438\u0441\u043A\u0443\", \"zh-cn\": \"\u91CD\u590D\u64AD\u653E\u5217\u8868\u56FE\u7247\" },\n \"imageshuffle0\": { \"en\": \"Picture without\", \"de\": \"Bild ohne Zufallswiedergabe\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u043C\u0435\u0448\u0438\u0432\u0430\u043D\u0438\u044F\", \"pt\": \"Imagem sem reprodu\u00E7\u00E3o aleat\u00F3ria\", \"nl\": \"Afbeelding zonder willekeurig afspelen\", \"fr\": \"Image sans lecture al\u00E9atoire\", \"it\": \"Immagine senza riproduzione casuale\", \"es\": \"Imagen sin reproducci\u00F3n aleatoria\", \"pl\": \"Obraz bez odtwarzania losowego\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u0431\u0435\u0437 \u043F\u0435\u0440\u0435\u043C\u0456\u0448\u0443\u0432\u0430\u043D\u043D\u044F\", \"zh-cn\": \"\u4E0D\u968F\u673A\u64AD\u653E\u56FE\u7247\" },\n \"imageshuffle1\": { \"en\": \"Picture Title\", \"de\": \"Bild Titel zuf\u00E4llig\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u0448\u0438\u0432\u0430\u043D\u0438\u044F \u0442\u0440\u0435\u043A\u043E\u0432\", \"pt\": \"Imagem de faixas aleat\u00F3rias\", \"nl\": \"Afbeelding titels willekeurig\", \"fr\": \"Image des titres al\u00E9atoires\", \"it\": \"Immagine titoli casuali\", \"es\": \"Imagen de t\u00EDtulos aleatorios\", \"pl\": \"Obraz losowania utwor\u00F3w\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043C\u0456\u0448\u0443\u0432\u0430\u043D\u043D\u044F \u0442\u0440\u0435\u043A\u0456\u0432\", \"zh-cn\": \"\u968F\u673A\u66F2\u76EE\u56FE\u7247\" },\n \"imageshuffle2\": { \"en\": \"Picture Album\", \"de\": \"Bild Album zuf\u00E4llig\", \"ru\": \"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u0448\u0438\u0432\u0430\u043D\u0438\u044F \u0430\u043B\u044C\u0431\u043E\u043C\u043E\u0432\", \"pt\": \"Imagem de \u00E1lbuns aleat\u00F3rios\", \"nl\": \"Afbeelding albums willekeurig\", \"fr\": \"Image des albums al\u00E9atoires\", \"it\": \"Immagine album casuali\", \"es\": \"Imagen de \u00E1lbumes aleatorios\", \"pl\": \"Obraz losowania album\u00F3w\", \"uk\": \"\u0417\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043C\u0456\u0448\u0443\u0432\u0430\u043D\u043D\u044F \u0430\u043B\u044C\u0431\u043E\u043C\u0456\u0432\", \"zh-cn\": \"\u968F\u673A\u4E13\u8F91\u56FE\u7247\" },\n \"bordercolornogroup\": { \"en\": \"Border color - No group\", \"de\": \"Rahmenfarbe \u2013 Keine Gruppe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0431\u0435\u0437 \u0433\u0440\u0443\u043F\u043F\u044B\", \"pt\": \"Cor da borda \u2014 sem grupo\", \"nl\": \"Randkleur \u2014 geen groep\", \"fr\": \"Couleur de bordure \u2014 aucun groupe\", \"it\": \"Colore bordo \u2014 nessun gruppo\", \"es\": \"Color del borde \u2014 sin grupo\", \"pl\": \"Kolor obramowania \u2014 brak grupy\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0431\u0435\u0437 \u0433\u0440\u0443\u043F\u0438\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272 \u2014 \u65E0\u7EC4\" },\n \"bordercolorowngroup\": { \"en\": \"Border color - Own group\", \"de\": \"Rahmenfarbe \u2013 Eigene Gruppe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0441\u0432\u043E\u044F \u0433\u0440\u0443\u043F\u043F\u0430\", \"pt\": \"Cor da borda \u2014 grupo pr\u00F3prio\", \"nl\": \"Randkleur \u2014 eigen groep\", \"fr\": \"Couleur de bordure \u2014 groupe propre\", \"it\": \"Colore bordo \u2014 gruppo proprio\", \"es\": \"Color del borde \u2014 grupo propio\", \"pl\": \"Kolor obramowania \u2014 w\u0142asna grupa\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0432\u043B\u0430\u0441\u043D\u0430 \u0433\u0440\u0443\u043F\u0430\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272 \u2014 \u81EA\u5DF1\u7684\u7EC4\" },\n \"bordercolorothergroup\": { \"en\": \"Border color - Other group\", \"de\": \"Rahmenfarbe \u2013 Andere Gruppe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0434\u0440\u0443\u0433\u0430\u044F \u0433\u0440\u0443\u043F\u043F\u0430\", \"pt\": \"Cor da borda \u2014 outro grupo\", \"nl\": \"Randkleur \u2014 andere groep\", \"fr\": \"Couleur de bordure \u2014 autre groupe\", \"it\": \"Colore bordo \u2014 altro gruppo\", \"es\": \"Color del borde \u2014 otro grupo\", \"pl\": \"Kolor obramowania \u2014 inna grupa\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438 \u2014 \u0456\u043D\u0448\u0430 \u0433\u0440\u0443\u043F\u0430\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272 \u2014 \u5176\u4ED6\u7EC4\" },\n \"group_rowsettings\": { \"en\": \"Row settings\", \"de\": \"Zeilenkonfiguration\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0441\u0442\u0440\u043E\u043A\u0438\", \"pt\": \"Defini\u00E7\u00F5es da linha\", \"nl\": \"Rij-instellingen\", \"fr\": \"Param\u00E8tres de ligne\", \"it\": \"Impostazioni riga\", \"es\": \"Ajustes de fila\", \"pl\": \"Ustawienia wiersza\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0440\u044F\u0434\u043A\u0430\", \"zh-cn\": \"\u884C\u8BBE\u7F6E\" },\n \"rowBackground\": { \"en\": \"Row background color\", \"de\": \"Hintergrundfarbe einer Zeile\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430 \u0441\u0442\u0440\u043E\u043A\u0438\", \"pt\": \"Cor de fundo da linha\", \"nl\": \"Achtergrondkleur rij\", \"fr\": \"Couleur d'arri\u00E8re-plan de la ligne\", \"it\": \"Colore di sfondo della riga\", \"es\": \"Color de fondo de la fila\", \"pl\": \"Kolor t\u0142a wiersza\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0444\u043E\u043D\u0443 \u0440\u044F\u0434\u043A\u0430\", \"zh-cn\": \"\u884C\u80CC\u666F\u989C\u8272\" },\n \"activeRowBackground\": { \"en\": \"Active row background color\", \"de\": \"Hintergrundfarbe der aktiven Zeile\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0444\u043E\u043D\u0430 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0438\", \"pt\": \"Cor de fundo da linha ativa\", \"nl\": \"Achtergrondkleur actieve rij\", \"fr\": \"Couleur d'arri\u00E8re-plan de la ligne active\", \"it\": \"Colore di sfondo della riga attiva\", \"es\": \"Color de fondo de la fila activa\", \"pl\": \"Kolor t\u0142a aktywnego wiersza\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0444\u043E\u043D\u0443 \u0430\u043A\u0442\u0438\u0432\u043D\u043E\u0433\u043E \u0440\u044F\u0434\u043A\u0430\", \"zh-cn\": \"\u6D3B\u52A8\u884C\u80CC\u666F\u989C\u8272\" },\n \"rowBorderColor\": { \"en\": \"Border color\", \"de\": \"Rahmenfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor da borda\", \"nl\": \"Randkleur\", \"fr\": \"Couleur de bordure\", \"it\": \"Colore bordo\", \"es\": \"Color del borde\", \"pl\": \"Kolor obramowania\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272\" },\n \"rowBorderWidth\": { \"en\": \"Border width\", \"de\": \"Rahmenbreite\", \"ru\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Largura da borda\", \"nl\": \"Randbreedte\", \"fr\": \"Largeur de bordure\", \"it\": \"Larghezza bordo\", \"es\": \"Anchura del borde\", \"pl\": \"Szeroko\u015B\u0107 obramowania\", \"uk\": \"\u0428\u0438\u0440\u0438\u043D\u0430 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u5BBD\u5EA6\" },\n \"rowBorderStyle\": { \"en\": \"Border style\", \"de\": \"Rahmenart\", \"ru\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Estilo da borda\", \"nl\": \"Randstijl\", \"fr\": \"Style de bordure\", \"it\": \"Stile bordo\", \"es\": \"Estilo del borde\", \"pl\": \"Styl obramowania\", \"uk\": \"\u0421\u0442\u0438\u043B\u044C \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u6837\u5F0F\" },\n \"rowSpacing\": { \"en\": \"Spacing to next track\", \"de\": \"Abstand zum n\u00E4chsten Titel\", \"ru\": \"\u0418\u043D\u0442\u0435\u0440\u0432\u0430\u043B \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u0442\u0440\u0435\u043A\u0430\", \"pt\": \"Espa\u00E7o at\u00E9 \u00E0 faixa seguinte\", \"nl\": \"Afstand tot volgende nummer\", \"fr\": \"Espacement jusqu'au titre suivant\", \"it\": \"Spaziatura dal brano successivo\", \"es\": \"Espacio hasta la pista siguiente\", \"pl\": \"Odst\u0119p do nast\u0119pnego utworu\", \"uk\": \"\u0412\u0456\u0434\u0441\u0442\u0443\u043F \u0434\u043E \u043D\u0430\u0441\u0442\u0443\u043F\u043D\u043E\u0433\u043E \u0442\u0440\u0435\u043A\u0443\", \"zh-cn\": \"\u4E0E\u4E0B\u4E00\u66F2\u76EE\u7684\u95F4\u8DDD\" },\n \"showThumbnail\": { \"en\": \"Show thumbnail\", \"de\": \"Thumbnail anzeigen\", \"ru\": \"\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043C\u0438\u043D\u0438\u0430\u0442\u044E\u0440\u0443\", \"pt\": \"Mostrar miniatura\", \"nl\": \"Miniatuur tonen\", \"fr\": \"Afficher la miniature\", \"it\": \"Mostra miniatura\", \"es\": \"Mostrar miniatura\", \"pl\": \"Poka\u017C miniatur\u0119\", \"uk\": \"\u041F\u043E\u043A\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043C\u0456\u043D\u0456\u0430\u0442\u044E\u0440\u0443\", \"zh-cn\": \"\u663E\u793A\u7F29\u7565\u56FE\" },\n \"showIndex\": { \"en\": \"Show track index\", \"de\": \"Titelindex anzeigen\", \"ru\": \"\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043D\u043E\u043C\u0435\u0440 \u0442\u0440\u0435\u043A\u0430\", \"pt\": \"Mostrar \u00EDndice da faixa\", \"nl\": \"Nummerindex tonen\", \"fr\": \"Afficher l'index du titre\", \"it\": \"Mostra indice del brano\", \"es\": \"Mostrar \u00EDndice de pista\", \"pl\": \"Poka\u017C indeks utworu\", \"uk\": \"\u041F\u043E\u043A\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u043D\u043E\u043C\u0435\u0440 \u0442\u0440\u0435\u043A\u0443\", \"zh-cn\": \"\u663E\u793A\u66F2\u76EE\u7D22\u5F15\" },\n \"buttonmargin\": { \"en\": \"Button spacing\", \"de\": \"Abstand zwischen Schaltfl\u00E4chen\", \"ru\": \"\u0420\u0430\u0441\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u043C\u0435\u0436\u0434\u0443 \u043A\u043D\u043E\u043F\u043A\u0430\u043C\u0438\", \"pt\": \"Espa\u00E7amento entre bot\u00F5es\", \"nl\": \"Afstand tussen knoppen\", \"fr\": \"Espacement entre les boutons\", \"it\": \"Spaziatura tra i pulsanti\", \"es\": \"Espacio entre botones\", \"pl\": \"Odst\u0119p mi\u0119dzy przyciskami\", \"uk\": \"\u0412\u0456\u0434\u0441\u0442\u0430\u043D\u044C \u043C\u0456\u0436 \u043A\u043D\u043E\u043F\u043A\u0430\u043C\u0438\", \"zh-cn\": \"\u6309\u94AE\u95F4\u8DDD\" },\n \"favoriteConfiguration\": { \"en\": \"Favorite configuration\", \"de\": \"Favoritenkonfiguration\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u0438\u0437\u0431\u0440\u0430\u043D\u043D\u043E\u0433\u043E\", \"pt\": \"Configura\u00E7\u00E3o de favoritos\", \"nl\": \"Favorietenconfiguratie\", \"fr\": \"Configuration des favoris\", \"it\": \"Configurazione dei preferiti\", \"es\": \"Configuraci\u00F3n de favoritos\", \"pl\": \"Konfiguracja ulubionych\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u0431\u0440\u0430\u043D\u043E\u0433\u043E\", \"zh-cn\": \"\u6536\u85CF\u914D\u7F6E\" },\n \"formatbutton\": { \"en\": \"Buttons\", \"de\": \"Schaltfl\u00E4chen\", \"ru\": \"\u041A\u043D\u043E\u043F\u043A\u0438\", \"pt\": \"Bot\u00F5es\", \"nl\": \"Knoppen\", \"fr\": \"Boutons\", \"it\": \"Pulsanti\", \"es\": \"Botones\", \"pl\": \"Przyciski\", \"uk\": \"\u041A\u043D\u043E\u043F\u043A\u0438\", \"zh-cn\": \"\u6309\u94AE\" },\n \"formatselect\": { \"en\": \"Selection list\", \"de\": \"Auswahlliste\", \"ru\": \"\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u044B\u0431\u043E\u0440\u0430\", \"pt\": \"Lista de sele\u00E7\u00E3o\", \"nl\": \"Keuzelijst\", \"fr\": \"Liste de s\u00E9lection\", \"it\": \"Elenco di selezione\", \"es\": \"Lista de selecci\u00F3n\", \"pl\": \"Lista wyboru\", \"uk\": \"\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u0438\u0431\u043E\u0440\u0443\", \"zh-cn\": \"\u9009\u62E9\u5217\u8868\" },\n \"formattype\": { \"en\": \"Display format\", \"de\": \"Anzeigeformat\", \"ru\": \"\u0424\u043E\u0440\u043C\u0430\u0442 \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F\", \"pt\": \"Formato de exibi\u00E7\u00E3o\", \"nl\": \"Weergaveformaat\", \"fr\": \"Format d'affichage\", \"it\": \"Formato di visualizzazione\", \"es\": \"Formato de visualizaci\u00F3n\", \"pl\": \"Format wy\u015Bwietlania\", \"uk\": \"\u0424\u043E\u0440\u043C\u0430\u0442 \u0432\u0456\u0434\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u663E\u793A\u683C\u5F0F\" },\n \"playerConfiguration\": { \"en\": \"Player configuration\", \"de\": \"Playerkonfiguration\", \"ru\": \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043F\u0440\u043E\u0438\u0433\u0440\u044B\u0432\u0430\u0442\u0435\u043B\u0435\u0439\", \"pt\": \"Configura\u00E7\u00E3o dos leitores\", \"nl\": \"Spelerconfiguratie\", \"fr\": \"Configuration des lecteurs\", \"it\": \"Configurazione dei lettori\", \"es\": \"Configuraci\u00F3n de reproductores\", \"pl\": \"Konfiguracja odtwarzaczy\", \"uk\": \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u043F\u0440\u043E\u0433\u0440\u0430\u0432\u0430\u0447\u0456\u0432\", \"zh-cn\": \"\u64AD\u653E\u5668\u914D\u7F6E\" },\n \"mainbarcolor\": { \"en\": \"Main bar color\", \"de\": \"Farbe der Hauptleiste\", \"ru\": \"\u0426\u0432\u0435\u0442 \u043E\u0441\u043D\u043E\u0432\u043D\u043E\u0439 \u043F\u043E\u043B\u043E\u0441\u044B\", \"pt\": \"Cor da barra principal\", \"nl\": \"Kleur van de hoofdbalk\", \"fr\": \"Couleur de la barre principale\", \"it\": \"Colore della barra principale\", \"es\": \"Color de la barra principal\", \"pl\": \"Kolor paska g\u0142\u00F3wnego\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u043E\u0441\u043D\u043E\u0432\u043D\u043E\u0457 \u0441\u043C\u0443\u0433\u0438\", \"zh-cn\": \"\u4E3B\u8FDB\u5EA6\u6761\u989C\u8272\" },\n \"playtimebarcolor\": { \"en\": \"Elapsed time bar color\", \"de\": \"Farbe der Laufzeitleiste\", \"ru\": \"\u0426\u0432\u0435\u0442 \u043F\u043E\u043B\u043E\u0441\u044B \u043F\u0440\u043E\u0448\u0435\u0434\u0448\u0435\u0433\u043E \u0432\u0440\u0435\u043C\u0435\u043D\u0438\", \"pt\": \"Cor da barra de tempo decorrido\", \"nl\": \"Kleur van de verstreken-tijdbalk\", \"fr\": \"Couleur de la barre du temps \u00E9coul\u00E9\", \"it\": \"Colore della barra del tempo trascorso\", \"es\": \"Color de la barra de tiempo transcurrido\", \"pl\": \"Kolor paska up\u0142ywu czasu\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0441\u043C\u0443\u0433\u0438 \u043C\u0438\u043D\u0443\u043B\u043E\u0433\u043E \u0447\u0430\u0441\u0443\", \"zh-cn\": \"\u5DF2\u64AD\u653E\u65F6\u95F4\u6761\u989C\u8272\" },\n \"bordercolor\": { \"en\": \"Border color\", \"de\": \"Rahmenfarbe\", \"ru\": \"\u0426\u0432\u0435\u0442 \u0440\u0430\u043C\u043A\u0438\", \"pt\": \"Cor da borda\", \"nl\": \"Randkleur\", \"fr\": \"Couleur de bordure\", \"it\": \"Colore bordo\", \"es\": \"Color del borde\", \"pl\": \"Kolor obramowania\", \"uk\": \"\u041A\u043E\u043B\u0456\u0440 \u0440\u0430\u043C\u043A\u0438\", \"zh-cn\": \"\u8FB9\u6846\u989C\u8272\" },\n \"playerattribute\": { \"en\": \"Player attribute\", \"de\": \"Player-Attribut\", \"ru\": \"\u0410\u0442\u0440\u0438\u0431\u0443\u0442 \u043F\u0440\u043E\u0438\u0433\u0440\u044B\u0432\u0430\u0442\u0435\u043B\u044F\", \"pt\": \"Atributo do leitor\", \"nl\": \"Spelerattribuut\", \"fr\": \"Attribut du lecteur\", \"it\": \"Attributo del lettore\", \"es\": \"Atributo del reproductor\", \"pl\": \"Atrybut odtwarzacza\", \"uk\": \"\u0410\u0442\u0440\u0438\u0431\u0443\u0442 \u043F\u0440\u043E\u0433\u0440\u0430\u0432\u0430\u0447\u0430\", \"zh-cn\": \"\u64AD\u653E\u5668\u5C5E\u6027\" },\n \"format\": { \"en\": \"Format\", \"de\": \"Format\", \"ru\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"pt\": \"Formato\", \"nl\": \"Indeling\", \"fr\": \"Format\", \"it\": \"Formato\", \"es\": \"Formato\", \"pl\": \"Format\", \"uk\": \"\u0424\u043E\u0440\u043C\u0430\u0442\", \"zh-cn\": \"\u683C\u5F0F\" },\n \"debug\": { \"en\": \"Debug\", \"de\": \"Debug-Ausgaben\", \"ru\": \"\u041E\u0442\u043B\u0430\u0434\u043A\u0430\", \"pt\": \"Depura\u00E7\u00E3o\", \"nl\": \"Foutopsporing\", \"fr\": \"D\u00E9bogage\", \"it\": \"Debug\", \"es\": \"Depuraci\u00F3n\", \"pl\": \"Debugowanie\", \"uk\": \"\u041D\u0430\u043B\u0430\u0433\u043E\u0434\u0436\u0435\u043D\u043D\u044F\", \"zh-cn\": \"\u8C03\u8BD5\" },\n \"debugwithFetchResults\": { \"en\": \"Debug with fetched results\", \"de\": \"Debug-Ausgaben mit abgerufenen Ergebnissen\", \"ru\": \"\u041E\u0442\u043B\u0430\u0434\u043A\u0430 \u0441 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043D\u044B\u043C\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0430\u043C\u0438\", \"pt\": \"Depura\u00E7\u00E3o com resultados obtidos\", \"nl\": \"Foutopsporing met opgehaalde resultaten\", \"fr\": \"D\u00E9bogage avec les r\u00E9sultats r\u00E9cup\u00E9r\u00E9s\", \"it\": \"Debug con i risultati recuperati\", \"es\": \"Depuraci\u00F3n con los resultados obtenidos\", \"pl\": \"Debugowanie z pobranymi wynikami\", \"uk\": \"\u041D\u0430\u043B\u0430\u0433\u043E\u0434\u0436\u0435\u043D\u043D\u044F \u0437 \u043E\u0442\u0440\u0438\u043C\u0430\u043D\u0438\u043C\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0430\u043C\u0438\", \"zh-cn\": \"\u8C03\u8BD5\u5E76\u8F93\u51FA\u83B7\u53D6\u7ED3\u679C\" }\n}\n", "/* xeslint no-extend-native: 0 */\n/* globals navigator */\n(function () {\n // Defining locale\n Date.shortMonths = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\n Date.longMonths = [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"];\n Date.shortDays = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n Date.longDays = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\n // Defining patterns\n const replaceChars = {\n // Day\n d: function () { const d = this.getDate(); return (d < 10 ? \"0\" : \"\") + d; },\n D: function () { return Date.shortDays[this.getDay()]; },\n j: function () { return this.getDate(); },\n l: function () { return Date.longDays[this.getDay()]; },\n N: function () { const N = this.getDay(); return (N === 0 ? 7 : N); },\n S: function () { const S = this.getDate(); return (S % 10 === 1 && S !== 11 ? \"st\" : (S % 10 === 2 && S !== 12 ? \"nd\" : (S % 10 === 3 && S !== 13 ? \"rd\" : \"th\"))); },\n w: function () { return this.getDay(); },\n z: function () { const d = new Date(this.getFullYear(), 0, 1); return Math.ceil((this - d) / 86400000); },\n // Week\n W: function () {\n const target = new Date(this.valueOf());\n const dayNr = (this.getDay() + 6) % 7;\n target.setDate(target.getDate() - dayNr + 3);\n const firstThursday = target.valueOf();\n target.setMonth(0, 1);\n if (target.getDay() !== 4) {\n target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);\n }\n const retVal = 1 + Math.ceil((firstThursday - target) / 604800000);\n\n return (retVal < 10 ? \"0\" + retVal : retVal);\n },\n // Month\n F: function () { return Date.longMonths[this.getMonth()]; },\n m: function () { const m = this.getMonth(); return (m < 9 ? \"0\" : \"\") + (m + 1); },\n M: function () { return Date.shortMonths[this.getMonth()]; },\n n: function () { return this.getMonth() + 1; },\n t: function () {\n let year = this.getFullYear();\n let nextMonth = this.getMonth() + 1;\n if (nextMonth === 12) {\n year = year++;\n nextMonth = 0;\n }\n return new Date(year, nextMonth, 0).getDate();\n },\n // Year\n L: function () { const L = this.getFullYear(); return (L % 400 === 0 || (L % 100 !== 0 && L % 4 === 0)); },\n o: function () { const d = new Date(this.valueOf()); d.setDate(d.getDate() - ((this.getDay() + 6) % 7) + 3); return d.getFullYear(); },\n Y: function () { return this.getFullYear(); },\n y: function () { return (\"\" + this.getFullYear()).substr(2); },\n // Time\n a: function () { return this.getHours() < 12 ? \"am\" : \"pm\"; },\n A: function () { return this.getHours() < 12 ? \"AM\" : \"PM\"; },\n B: function () { return Math.floor((((this.getUTCHours() + 1) % 24) + this.getUTCMinutes() / 60 + this.getUTCSeconds() / 3600) * 1000 / 24); },\n g: function () { return this.getHours() % 12 || 12; },\n G: function () { return this.getHours(); },\n h: function () { const h = this.getHours(); return ((h % 12 || 12) < 10 ? \"0\" : \"\") + (h % 12 || 12); },\n H: function () { const H = this.getHours(); return (H < 10 ? \"0\" : \"\") + H; },\n i: function () { const i = this.getMinutes(); return (i < 10 ? \"0\" : \"\") + i; },\n s: function () { const s = this.getSeconds(); return (s < 10 ? \"0\" : \"\") + s; },\n v: function () { const v = this.getMilliseconds(); return (v < 10 ? \"00\" : (v < 100 ? \"0\" : \"\")) + v; },\n // Timezone\n e: function () { return Intl.DateTimeFormat().resolvedOptions().timeZone; },\n I: function () {\n let DST = null;\n for (let i = 0; i < 12; ++i) {\n const d = new Date(this.getFullYear(), i, 1);\n const offset = d.getTimezoneOffset();\n\n if (DST === null) DST = offset;\n else if (offset < DST) { DST = offset; break; } else if (offset > DST) break;\n }\n return (this.getTimezoneOffset() === DST) | 0;\n },\n O: function () { const O = this.getTimezoneOffset(); return (-O < 0 ? \"-\" : \"+\") + (Math.abs(O / 60) < 10 ? \"0\" : \"\") + Math.floor(Math.abs(O / 60)) + (Math.abs(O % 60) === 0 ? \"00\" : ((Math.abs(O % 60) < 10 ? \"0\" : \"\")) + (Math.abs(O % 60))); },\n P: function () { const P = this.getTimezoneOffset(); return (-P < 0 ? \"-\" : \"+\") + (Math.abs(P / 60) < 10 ? \"0\" : \"\") + Math.floor(Math.abs(P / 60)) + \":\" + (Math.abs(P % 60) === 0 ? \"00\" : ((Math.abs(P % 60) < 10 ? \"0\" : \"\")) + (Math.abs(P % 60))); },\n T: function () { const tz = this.toLocaleTimeString(navigator.language, { timeZoneName: \"short\" }).split(\" \"); return tz[tz.length - 1]; },\n Z: function () { return -this.getTimezoneOffset() * 60; },\n // Full Date/Time\n c: function () { return this.format(\"Y-m-d\\\\TH:i:sP\"); },\n r: function () { return this.toString(); },\n U: function () { return Math.floor(this.getTime() / 1000); }\n };\n\n // Simulates PHP's date function\n Date.prototype.format = function (format) {\n const date = this;\n return format.replace(/(\\\\?)(.)/g, function (_, esc, chr) {\n return (esc === \"\" && replaceChars[chr]) ? replaceChars[chr].call(date) : chr;\n });\n };\n}).call(this);", "'use strict';\n\n/**\n * This function takes a request and returns an appropriate class that can parse the response.\n * The class is determined by the content of the response.\n *\n * @param request - The request object.\n * @returns The class that can parse the response.\n */\nexport function parseRequestFactory(request) {\n console.log(`parseRequestFactory`);\n let result = request.result;\n if (result.albums_loop) {\n return new Albums(request);\n }\n if (result.artists_loop) {\n return new Artists(request);\n }\n if (result.genres_loop) {\n return new Genres(request);\n }\n if (result.works_loop) {\n return new Works(request);\n }\n if (result.years_loop) {\n return new Years(request);\n }\n if (result.item_loop) {\n return new Items(request);\n }\n if (result.titles_loop) {\n return new Tracks(request);\n }\n if (result.playlisttracks_loop) {\n return new PlaylistTracks(request);\n }\n if (result.playlists_loop) {\n return new Playlists(request);\n }\n //specialHandling\n let requestCommand = request.params[1][0];\n if (requestCommand === 'selectVirtualLibrary' && !result.item_loop) {\n return new Items(request);\n }\n}\nclass Albums {\n constructor(request) {\n console.log(`Albums`);\n this.albums = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.albums_loop) {\n let albums = result.albums_loop;\n return albums.map(item => {\n return new Album(item, request);\n });\n }\n }\n getMenuItems() {\n return this.albums.map(item => item.getMenu());\n }\n}\nclass Album {\n constructor(request_item, request) {\n this.parseRequest(request_item, request);\n }\n parseRequest(request_item, request) {\n this.id = request_item.id || undefined;\n this.performance = request_item.performance || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.favorites_title = request_item.favorites_title || undefined;\n this.album = request_item.album || undefined;\n this.year = request_item.year || undefined;\n this.artwork_track_id = request_item.artwork_track_id || undefined;\n this.compilation = request_item.compilation || undefined;\n this.artist_id = request_item.artist_id || undefined;\n this.artist = request_item.artist || undefined;\n this.textkey = request_item.textkey || undefined;\n let additionalPlayParams = [getParamsFromCommand(request.params[1], 'role_id:')];\n this.actions = {\n next: {\n command: ['tracks'],\n params: ['tags:distbhz1kyuAACGPSE', 'sort:tracknum', `album_id:${this.id}`],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `album_id:${this.id}`, `performance:`, ...additionalPlayParams, `library_id:-1`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `album_id:${this.id}`, `performance:`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: `${this.artist} / ${this.album} ${this.year ? `(${this.year})` : ''}`,\n image: `/music/${this.artwork_track_id}/cover_300x300_f`,\n type: 'album',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass Artists {\n constructor(request) {\n console.log(`Artists`);\n this.artists = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.artists_loop) {\n let artists = result.artists_loop;\n return artists.map(item => {\n return new Artist(item, request);\n });\n }\n }\n getMenuItems() {\n return this.artists.map(item => item.getMenu());\n }\n}\nclass Artist {\n constructor(request_item, request) {\n this.parseRequest(request_item, request);\n }\n parseRequest(request_item, request) {\n this.id = request_item.id || undefined;\n this.artist = request_item.artist || undefined;\n this.textkey = request_item.textkey || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n let additionalPlayParams = [getParamsFromCommand(request.params[1], 'role_id:')];\n this.actions = {\n next: {\n command: ['albums'],\n params: ['tags:aajlqswyKSSE', 'sort:yearalbum', `artist_id:${this.id}`],\n },\n play: {\n command: ['playlistcontrol'],\n params: [\n `cmd:load`,\n `role_id:ALBUMARTIST`,\n `artist_id:${this.id}`,\n `sort:yearalbum`,\n ...additionalPlayParams,\n `library_id:-1`,\n ],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `role_id:ALBUMARTIST`, `artist_id:${this.id}`, `sort:yearalbum`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: this.artist,\n image: `/imageproxy/mai/artist/${this.id}/image_300x300_f`,\n type: 'artist',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass Genres {\n constructor(request) {\n console.log(`Genres`);\n this.genres = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.genres_loop) {\n let genres = result.genres_loop;\n return genres.map(item => {\n return new Genre(item);\n });\n }\n }\n getMenuItems() {\n return this.genres.map(item => item.getMenu());\n }\n}\nclass Genre {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.genre = request_item.genre || undefined;\n this.textkey = request_item.textkey || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.actions = {\n next: {\n command: ['tracks'],\n params: [`genre_id:${request_item.id}`, 'tags:distbhz1kyuAACGPScelyE', 'msk-sort:yearalbumtrack:Album'],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `genre_id:${this.id}`, `sort:album`, `library_id:-1`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `genre_id:${this.id}`, `sort:album`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: `${this.genre}`,\n image: null,\n type: 'genre',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass Playlists {\n constructor(request) {\n console.log(`Playlists`);\n this.playlists = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.playlists_loop) {\n let playlists = result.playlists_loop;\n return playlists.map(item => {\n return new Playlist(item);\n });\n }\n }\n getMenuItems() {\n return this.playlists.map(item => item.getMenu());\n }\n}\nclass Playlist {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.playlist = request_item.playlist || undefined;\n this.url = request_item.url || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.textkey = request_item.textkey || undefined;\n this.extid = request_item.extid || undefined;\n this.remote = request_item.remote || undefined;\n this.actions = {\n next: {\n command: ['playlists', 'tracks'],\n params: [`playlist_id:${request_item.id}`, 'tags:distbhz1acelyAGKPS'],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `playlist_id:${this.id}`, `performance:`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `playlist_id:${this.id}`, `performance:`],\n },\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: `${this.playlist}`,\n image: null,\n type: 'playlist',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass Works {\n constructor(request) {\n console.log(`Works`);\n this.works = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.works_loop) {\n let works = result.works_loop;\n return works.map(item => {\n return new Work(item);\n });\n }\n }\n getMenuItems() {\n return this.works.map(item => item.getMenu());\n }\n}\nclass Work {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.work_id || undefined;\n this.composer = request_item.composer || undefined;\n this.work = request_item.work || undefined;\n this.composer_id = request_item.composer_id || undefined;\n this.album_id = request_item.album_id || undefined;\n this.textkey = request_item.textkey || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.favorites_title = request_item.favorites_title || undefined;\n this.actions = {\n next: {\n command: ['albums'],\n params: [\n 'tags:aajlqswyKSSE',\n `work_id:${this.id}`,\n `composer_id:${this.composer_id}`,\n `album_id:${this.album_id}`,\n ],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `work_id:${this.id}`, `album_id:${this.album_id}`, `performance:`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `work_id:${this.id}`, `album_id:${this.album_id}`, `performance:`],\n },\n };\n }\n getMenu() {\n return {\n id: `work_id:${this.id}`,\n title: `${this.favorites_title}`,\n image: null,\n type: 'work',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass Years {\n constructor(request) {\n console.log(`Years`);\n this.years = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.years_loop) {\n let years = result.years_loop;\n return years.map(item => {\n return new Year(item);\n });\n }\n }\n getMenuItems() {\n return this.years.map(item => item.getMenu());\n }\n}\nclass Year {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.year || undefined;\n this.year = request_item.year || undefined;\n this.favorites_url = request_item.favorites_url || undefined;\n this.actions = {\n next: {\n command: ['albums'],\n params: [\n 'release_type:Album',\n 'tags:aajlqswyKSSE',\n 'sort:album',\n 'menu:1',\n `year:${request_item.year}`,\n ],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `year:${this.id}`, `library_id:-1`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `year:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `year_id:${this.id}`,\n title: `${this.year}`,\n image: null,\n type: 'year',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass Tracks {\n constructor(request) {\n console.log(`Tracks`);\n this.tracks = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.titles_loop) {\n let tracks = result.titles_loop;\n return tracks.map(item => {\n return new Track(item);\n });\n }\n }\n getMenuItems() {\n return this.tracks.map(item => item.getMenu());\n }\n}\nclass Track {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.title = request_item.title || undefined;\n this.duration = request_item.duration || undefined;\n this.artist_id = request_item.artist_id || undefined;\n this.tracknum = request_item.tracknum || undefined;\n this.year = request_item.year || undefined;\n this.albumartist = request_item.albumartist || undefined;\n this.trackartist = request_item.trackartist || undefined;\n this.compilation = request_item.compilation || undefined;\n this.genres = request_item.genres || undefined;\n this.genre_ids = request_item.genre_ids || undefined;\n this.albumartist_ids = request_item.albumartist_ids || undefined;\n this.trackartist_ids = request_item.trackartist_ids || undefined;\n this.actions = {\n play: {\n command: ['playlistcontrol'],\n params: [`cmd:load`, `track_id:${this.id}`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`cmd:add`, `track_id:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `track_id:${this.id}`,\n title: `${this.title}`,\n image: null,\n type: 'track',\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass PlaylistTracks {\n constructor(request) {\n console.log(`PlaylistTracks`);\n this.playlisttracks = this.parseRequest(request);\n }\n parseRequest(request) {\n let result = request.result;\n if (result.playlisttracks_loop) {\n let playlisttracks = result.playlisttracks_loop;\n return playlisttracks.map(item => {\n return new PlaylistTrack(item);\n });\n }\n }\n getMenuItems() {\n return this.playlisttracks.map(item => item.getMenu());\n }\n}\nclass PlaylistTrack {\n constructor(request_item) {\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.id || undefined;\n this.title = request_item.title || undefined;\n this['playlist index'] = request_item['playlist index'] || undefined;\n this.title = request_item.title || undefined;\n this.duration = request_item.duration || undefined;\n this.artist_ids = request_item.artist_ids || undefined;\n this.tracknum = request_item.tracknum || undefined;\n this.artist = request_item.artist || undefined;\n this.coverid = request_item.coverid || undefined;\n this.album_id = request_item.album_id || undefined;\n this.album = request_item.album || undefined;\n this.year = request_item.year || undefined;\n this.genres = request_item.genres || undefined;\n this.genre_ids = request_item.genre_ids || undefined;\n this.artist_ids = request_item.artist_ids || undefined;\n this.actions = {\n next: {\n command: ['playlist', 'tracks'],\n params: ['tags:distbhz1acelyAGKPS', 'playlist_id:${this.id}'],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:load`, `folder_id:${this.id}`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:add`, `folder_id:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `track_id:${this.id}`,\n title: `${this.title}`,\n image: null,\n type: 'playlisttrack',\n item: this,\n };\n }\n}\nclass Items {\n constructor(request) {\n console.log(`Items`);\n let filesystem = request.params[1].includes('mode:filesystem');\n let requestCommand = request.params[1][0] + (filesystem ? 'FS' : '');\n this.items = this.parseRequest(request, requestCommand);\n }\n parseRequest(request, requestCommand) {\n let result = request.result;\n if (result.item_loop) {\n let items = result.item_loop;\n return items.map(item => {\n return Item.create(item, requestCommand, request);\n });\n }\n if (!result.titles_loop && requestCommand === 'selectVirtualLibrary') {\n return [\n Item.create(\n {\n type: 'virtualLibraryAnswer',\n text: request.result.title,\n },\n requestCommand,\n ),\n ];\n }\n }\n getMenuItems() {\n return this.items.map(item => item.getMenu());\n }\n}\nclass Item {\n // item types\n // search|text|textarea|audio|playlist|link|opml|replace|redirect|radio\n static create(request_item, requestCommand, request) {\n console.log(`Item switch: ${requestCommand}_${request_item.type || ''}`);\n switch (`${requestCommand}_${request_item.type || ''}`) {\n case 'radios_':\n case 'local_':\n case 'music_':\n case 'sports_':\n case 'news_':\n case 'talk_':\n case 'location_':\n case 'language_':\n case 'podcast_':\n case 'local_link':\n case 'music_link':\n case 'sports_link':\n case 'news_link':\n case 'talk_link':\n case 'location_link':\n case 'language_link':\n case 'podcast_link':\n return new ItemRadio(request_item, requestCommand);\n case 'local_text':\n case 'music_text':\n case 'sports_text':\n case 'news_text':\n case 'talk_text':\n case 'location_text':\n case 'language_text':\n case 'podcast_text':\n case 'browselibrary_text':\n case 'browselibraryFS_text':\n return new ItemText(request_item, requestCommand);\n case 'menu_':\n return new ItemMenu(request_item, request);\n case 'browselibrary_playlist':\n case 'favorites_playlist':\n return new ItemPlaylist(request_item, false);\n case 'browselibraryFS_playlist':\n return new ItemPlaylist(request_item, true);\n case 'browselibraryFS_':\n return new ItemFilesystem(request_item);\n case 'browselibrary_audio': //ok\n case 'browselibraryFS_audio': //ok\n case 'local_audio': //ok\n case 'music_audio': //ok\n case 'sports_audio': //ok\n case 'news_audio': //ok\n case 'talk_audio': //ok\n case 'location_audio': //ok\n case 'language_audio': //ok\n case 'podcast_audio': //ok\n case 'favorites_audio': //ok\n return new ItemAudio(request_item, requestCommand);\n case 'selectVirtualLibrary_virtualLibraryAnswer':\n return new ItemVirtualLibraryAnswer(request_item);\n case 'selectVirtualLibrary_':\n case 'selectVirtualLibrary_outline':\n return new ItemVirtualLibrary(request_item);\n case 'myapps_redirect':\n return new ItemApplication(request_item);\n default:\n return new ItemMenu(request_item, request);\n // debugger;\n // throw new Error(`Unknown item type: ${requestCommand}_${request_item.type || ''}`);\n }\n }\n}\nclass ItemApplication extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.actions.go.params.menu || undefined;\n this.text = request_item.text.trim() || undefined;\n this.iconid = request_item['icon-id'] || undefined;\n this.actions = {};\n if (request_item.actions['go']) {\n this.actions = {\n ...this.actions,\n ...{ next: translateMyMusicParameters(request_item.actions.go) },\n };\n }\n if (request_item.actions['play']) {\n this.actions = {\n ...this.actions,\n ...{ play: translateMyMusicParameters(request_item.actions.play) },\n };\n }\n if (request_item.actions['add']) {\n this.actions = {\n ...this.actions,\n ...{ add: translateMyMusicParameters(request_item.actions.add) },\n };\n }\n }\n getMenu() {\n return {\n id: this.id,\n title: this.text,\n image: this.icon,\n type: 'itemapplication',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemRadio extends Item {\n constructor(request_item, requestCommand) {\n super(request_item);\n this.parseRequest(request_item, requestCommand);\n }\n parseRequest(request_item, requestCommand) {\n let cmd;\n if (request_item.actions?.go) {\n cmd = translateMyMusicParameters(request_item.actions?.go);\n } else {\n cmd = {\n command: [requestCommand, 'items'],\n params: [`menu:${requestCommand}`, `item_id:${request_item.actions.go.params.item_id}`],\n };\n }\n this.id = request_item.actions.go.params.item_id || request_item.actions.go.params.menu || undefined;\n this.text = request_item.text || undefined;\n this.actions = {\n next: cmd,\n };\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'radiolocal',\n param: JSON.stringify(this.actions.next),\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemMenu extends Item {\n constructor(request_item, request) {\n super(request_item);\n this.parseRequest(request_item, request);\n }\n parseRequest(request_item, request) {\n this.id = request_item.text || undefined;\n this.text = request_item.text || 'Empty';\n this.node = request_item.node || undefined;\n this.weight = request_item.weight || undefined;\n if (request_item.actions) {\n if (request_item.actions['go']) {\n this.actions = {\n ...this.actions,\n ...{ next: translateMyMusicParameters(request_item.actions.go) },\n };\n }\n if (request_item.actions['play']) {\n this.actions = {\n ...this.actions,\n ...{ play: translateMyMusicParameters(request_item.actions.play) },\n };\n }\n if (request_item.actions['add']) {\n this.actions = {\n ...this.actions,\n ...{ add: translateMyMusicParameters(request_item.actions.add) },\n };\n }\n if (request_item.actions['do']) {\n this.actions = {\n ...this.actions,\n ...{ add: translateMyMusicParameters(request_item.actions.do) },\n };\n }\n }\n if (request_item.goAction) {\n if (request_item.goAction == 'play') {\n const filteredParams = Object.keys(request_item.params)\n .filter(key => !key.includes('touchToPlay'))\n .reduce((obj, key) => {\n obj[key] = request_item.params[key];\n return obj;\n }, {});\n this.actions = {\n play: {\n command: request.result.base.actions[request_item.goAction].cmd,\n params: [\n ...object2Array({\n ...request.result.base.actions[request_item.goAction].params,\n ...filteredParams,\n }),\n ],\n },\n };\n }\n }\n // if (request_item.actions) {\n // const priorityKeys = ['go', 'do'];\n // const goAction = priorityKeys.find(key => Object.prototype.hasOwnProperty.call(request_item.actions, key));\n // if (goAction) {\n // cmd = {\n // ...{ cmd: request_item.actions[goAction].cmd },\n // ...{ param: request_item.actions[goAction].param },\n // };\n // } else {\n // console.log('Please check: no valid action');\n // }\n\n // // cmd = {\n // // ...{ cmd: request.result.base.actions[goAction].cmd },\n // // ...{ param: request.result.base.actions[goAction].param },\n // // };\n // this.actions = {\n // next: cmd,\n // };\n // }\n }\n getMenu() {\n return {\n id: this.id,\n title: this.text,\n image: null,\n type: 'menu',\n actions: JSON.stringify(this.actions),\n item: this,\n };\n }\n}\nclass ItemFilesystem extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n let cmd;\n if (request_item.actions?.go) {\n cmd = translateMyMusicParameters(request_item.actions?.go);\n }\n\n this.id = request_item.actions?.go.params.item_id || undefined;\n this.text = request_item.text || undefined;\n this.actions = {\n next: cmd,\n };\n }\n getMenu() {\n return {\n id: this.id,\n title: this.text,\n image: null,\n type: 'menu',\n param: JSON.stringify(this.actions.next),\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemPlaylist extends Item {\n constructor(request_item, filesystem) {\n super(request_item);\n this.parseRequest(request_item, filesystem);\n }\n parseRequest(request_item, filesystem) {\n this.id = request_item.actions?.more.params.folder_id || undefined;\n this.text = request_item.text || undefined;\n this.textkey = request_item.textkey || undefined;\n this.actions = {\n next: {\n command: ['browselibrary', 'items'],\n params: [\n 'menu:browselibrary',\n filesystem ? 'mode:filesystem' : 'mode:bmf',\n ...object2Array(request_item.params),\n ],\n },\n play: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:load`, `folder_id:${this.id}`],\n },\n add: {\n command: ['playlistcontrol'],\n params: [`menu:1`, `cmd:add`, `folder_id:${this.id}`],\n },\n };\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: `(D) ${this.text}`,\n image: null,\n type: 'itemplaylist',\n param: JSON.stringify(this.actions.next),\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemText extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.text || undefined;\n this.text = request_item.text || undefined;\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'itemtext',\n param: null,\n item: this,\n };\n }\n}\nclass ItemAudio extends Item {\n constructor(request_item, requestCommand) {\n super(request_item);\n this.parseRequest(request_item, requestCommand);\n }\n parseRequest(request_item, requestCommand) {\n this.id = request_item.commonParams?.track_id || request_item.params?.item_id || undefined;\n this.text = request_item.text || undefined;\n this.textkey = request_item.textkey || undefined;\n this.icon = request_item.icon || undefined;\n this.iconid = request_item['icon-id'] || undefined;\n this.favorites_type = request_item.presetParams.favorites_type || undefined;\n this.favorites_url = request_item.presetParams.favorites_url || undefined;\n this.favorites_title = request_item.presetParams.favorites_title || undefined;\n this.icon = request_item.presetParams.icon || undefined;\n this.actions = {\n play: {\n command: [...(requestCommand === 'browselibraryFS' ? ['browselibrary'] : [requestCommand])],\n params: [\n 'playlist',\n 'play',\n ...(requestCommand === 'browselibrary' ? ['mode:bmf'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['mode:filesystem'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['menu:browselibrary'] : [requestCommand]),\n `item_id:${this.id}`,\n `isContextMenu:1`,\n ],\n },\n add: {\n command: [...(requestCommand === 'browselibraryFS' ? ['browselibrary'] : [requestCommand])],\n params: [\n 'playlist',\n 'add',\n ...(requestCommand === 'browselibrary' ? ['mode:bmf'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['mode:filesystem'] : []),\n ...(requestCommand === 'browselibraryFS' ? ['menu:browselibrary'] : [requestCommand]),\n `item_id:${this.id}`,\n `isContextMenu:1`,\n ],\n },\n };\n }\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: `${this.text}`,\n image: this.icon,\n type: 'itemaudio',\n item: this,\n actions: JSON.stringify(this.actions),\n };\n }\n}\nclass ItemVirtualLibrary extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.actions?.go.params.item_id || undefined;\n this.text = request_item.text || undefined;\n let cmd = {\n command: ['selectVirtualLibrary', 'items'],\n params: [`item_id:${request_item.actions.go.params.item_id}`, 'menu:selectVirtualLibrary'],\n };\n this.actions = {\n next: cmd,\n };\n\n /* \n {\n \"addAction\": \"go\",\n \"text\": \"All Library (Default)\",\n \"actions\": {\n \"go\": {\n \"cmd\": [\n \"selectVirtualLibrary\",\n \"items\"\n ],\n \"params\": {\n \"item_id\": \"0\",\n \"menu\": \"selectVirtualLibrary\"\n },\n \"nextWindow\": \"myMusic\"\n }\n }\n } */\n }\n\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'itemvirtuallibrary',\n item: this,\n param: JSON.stringify(this.actions.next),\n actions: JSON.stringify(this.actions),\n };\n }\n}\n\nclass ItemVirtualLibraryAnswer extends Item {\n constructor(request_item) {\n super(request_item);\n this.parseRequest(request_item);\n }\n parseRequest(request_item) {\n this.id = request_item.actions?.go.params.item_id || undefined;\n this.text = request_item.text || undefined;\n }\n\n getMenu() {\n return {\n id: `item_id:${this.id}`,\n title: this.text,\n image: null,\n type: 'itemvirtuallibraryanswer',\n item: this,\n param: null,\n };\n }\n}\nfunction object2Array(obj) {\n return Object.keys(obj).map(function (key) {\n return `${key}:${obj[key]}`;\n });\n}\nfunction getParamsFromCommand(params, key) {\n return params.find(item => item.toString().startsWith(key));\n}\nfunction translateMyMusicParameters(command /* , request */) {\n console.log(command);\n if (command.cmd == undefined) {\n return undefined;\n }\n var cmd = { command: [...command.cmd], params: [] };\n for (var key in command.params) {\n let p = command.params[key];\n if (p != undefined && p != null && p.length > 0) {\n cmd.params.push(`${key}:${p}`);\n }\n }\n\n let c = [];\n let p = [];\n var mode = undefined;\n var canReplace = true;\n var hasSort = false;\n var hasTags = false;\n var hasArtistId = false;\n var hasLibraryId = false;\n var hasNonArtistRole = false;\n for (let i = 0, params = cmd.params; i < cmd.params.length; i++) {\n if (params[i].startsWith('mode:')) {\n mode = params[i].split(':')[1];\n if (mode.startsWith('myMusicArtists')) {\n mode = 'artists';\n } else if (\n mode.startsWith('myMusicAlbums') ||\n mode == 'randomalbums' ||\n mode == 'vaalbums' ||\n mode == 'recentlychanged'\n ) {\n mode = 'albums';\n } else if (mode == 'years') {\n p.push('hasAlbums:1');\n } else if (mode.startsWith('myMusicWorks')) {\n mode = 'works';\n } else if (\n mode != 'artists' &&\n mode != 'albums' &&\n mode != 'genres' &&\n mode != 'tracks' &&\n mode != 'playlists' &&\n mode != 'works'\n ) {\n canReplace = false;\n break;\n }\n c.push(mode);\n }\n if (!params[i].startsWith('menu:')) {\n if (params[i].startsWith('tags:')) {\n if (params[i].split(':')[1].indexOf('s') < 0) {\n i += 's';\n }\n p.push(params[i]);\n hasTags = true;\n } else {\n p.push(params[i]);\n if (params[i].startsWith('sort:')) {\n hasSort = true;\n } else if (params[i].startsWith('artist_id:')) {\n hasArtistId = true;\n } else if (params[i].startsWith('library_id:')) {\n hasLibraryId = true;\n } else if (params[i].startsWith('role_id:')) {\n var role = params[i].split(':')[1].toLowerCase();\n if ('albumartist' != role && '5' != role) {\n hasNonArtistRole = true;\n }\n }\n }\n }\n }\n\n if (canReplace && c.length == 1 && mode) {\n if (mode == 'tracks') {\n if (!hasTags) {\n // If view.current.id starts with \"track_id:\" then we are in a 'More' menu, therefore\n // want cover id of tracks...\n // tags:distbhz1kyuAACGPSc\n p.push('tags:distbhz1kyuAACGPSc');\n }\n if (!hasSort) {\n p.push('sort:tracknum');\n }\n } else if (mode == 'albums') {\n if (!hasTags) {\n p.push(hasArtistId ? 'ArAlTP' : 'AlTP');\n }\n if (!hasSort) {\n p.push(`sort:album`);\n }\n } else if (mode == 'playlists') {\n if (!hasTags) {\n p.push('PlTP');\n }\n } else if (!hasTags) {\n if (mode == 'artists' || mode == 'vaalbums') {\n p.push('ArTP');\n if (!hasLibraryId && !hasNonArtistRole) {\n p.push('include_online_only_artists:1');\n }\n } else if (mode == 'years' || mode == 'genres') {\n p.push('tags:s');\n }\n }\n cmd = { command: c, params: p };\n }\n if (cmd.params.length > 0) {\n for (var i = 0, len = cmd.params.length; i < len; ++i) {\n cmd.params[i] = cmd.params[i]\n .replace('ArAlTP', 'tags:aajlqswyKRSSW2')\n .replace('ArTP', 'tags:s')\n .replace('PlTP', 'tags:suxE')\n .replace('AlTP', 'tags:ajlqswyKS2');\n }\n }\n cmd.params.push('menu:1');\n cmd.params.push('library_id:-1');\n return { ...cmd };\n}\n", "{\n \"name\": \"iobroker.squeezeboxrpc\",\n \"version\": \"3.0.0\",\n \"description\": \"ioBroker Logitech Squeezebox Adapter over JSON/RPC-Protocol\",\n \"author\": {\n \"name\": \"oweitman\",\n \"email\": \"oweitman@gmx.de\"\n },\n \"homepage\": \"https://github.com/oweitman/ioBroker.squeezeboxrpc\",\n \"license\": \"MIT\",\n \"keywords\": [\n \"ioBroker\",\n \"squeezebox\",\n \"LMS\",\n \"Logitech Media Server\",\n \"Lyrion Media Server\",\n \"music server\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/oweitman/ioBroker.squeezeboxrpc\"\n },\n \"engines\": {\n \"node\": \">= 22\"\n },\n \"dependencies\": {\n \"@iobroker/adapter-core\": \"^3.4.3\",\n \"ws\": \"^8.21.3\"\n },\n \"devDependencies\": {\n \"@alcalzone/release-script\": \"^5.2.1\",\n \"@alcalzone/release-script-plugin-iobroker\": \"^5.2.0\",\n \"@alcalzone/release-script-plugin-license\": \"^5.2.2\",\n \"@alcalzone/release-script-plugin-manual-review\": \"^5.2.0\",\n \"@iobroker/adapter-dev\": \"^1.5.0\",\n \"@iobroker/build-tools\": \"^3.0.1\",\n \"@iobroker/eslint-config\": \"^2.2.0\",\n \"@iobroker/testing\": \"^5.2.2\",\n \"@tsconfig/node22\": \"^22.0.5\",\n \"@types/node\": \"^22.20.1\",\n \"@types/proxyquire\": \"^1.3.31\",\n \"proxyquire\": \"^2.1.3\",\n \"typescript\": \"~5.9.3\"\n },\n \"main\": \"squeezeboxrpc.js\",\n \"files\": [\n \"admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).{json,json5}\",\n \"admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}\",\n \"lib/\",\n \"widgets/*.html\",\n \"widgets/!(node_modules)/**/build/*.{js,map}\",\n \"widgets/!(node_modules)/**/css/*.css\",\n \"widgets/!(node_modules)/**/img/*.{png,svg,jpg}\",\n \"widgets/vis2squeezeboxrpc/\",\n \"www/\",\n \"io-package.json\",\n \"LICENSE\",\n \"main.js\"\n ],\n \"scripts\": {\n \"test:js\": \"mocha --config test/mocharc.custom.json \\\"*.test.js\\\" \\\"test/**/*.test.js\\\"\",\n \"test:package\": \"mocha test/package --exit\",\n \"test:integration\": \"mocha test/integration --exit\",\n \"test\": \"npm run test:js && npm run test:package\",\n \"check\": \"tsc --noEmit -p tsconfig.check.json\",\n \"lint\": \"npm run lint-adapter && npm run lint-vis1widgets && npm run lint-vis2widgets\",\n \"lint-adapter\": \"eslint -c eslint.config.mjs . --ignore-pattern src-widgets/ --ignore-pattern widgets/squeezeboxrpc/js/ --ignore-pattern widgets/vis2squeezeboxrpc/\",\n \"lint-vis1widgets\": \"eslint -c eslint.config.mjs widgets/squeezeboxrpc/js\",\n \"lint-vis2widgets\": \"cd src-widgets && npm run lint && cd ..\",\n \"npm\": \"npm run npm:main && npm run npm:vis1widgets && npm run npm:vis2widgets\",\n \"npm:main\": \"npm i\",\n \"npm:vis1widgets\": \"npm install --prefix widgets\",\n \"npm:vis2widgets\": \"cd src-widgets && npm i && cd ..\",\n \"devupload\": \"dev-server upload\",\n \"build\": \"npm run build-vis1widgets && npm run build-vis2widgets\",\n \"buildx\": \"npm run build-vis1widgets \",\n \"build-vis1widgets\": \"npm run build --prefix widgets\",\n \"build-vis2widgets\": \"node tasks --javascript-vite\",\n \"dev:upload\": \"dev-server upload\",\n \"dev:run\": \"dev-server run\",\n \"dev:watch\": \"dev-server watch --noStart\",\n \"dev:watchvis2widgets\": \"npm run start --prefix src-widgets\",\n \"dev:watchvis1widgets\": \"npm run watch --prefix widgets\",\n \"prepublishOnly\": \"npm run build\",\n \"repochecker\": \"npx @iobroker/repochecker https://github.com/oweitman/ioBroker.squeezeboxrpc --local --env=../iobroker.env\",\n \"translate\": \"translate-adapter\",\n \"translate-widgets\": \"node ./bin/translate.js --source widgets/squeezeboxrpc/myi18n/en.json --format single\",\n \"translate-lib\": \"node ./bin/translate.js --source lib/i18n/ --format multi\",\n \"release\": \"release-script --all\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/oweitman/ioBroker.squeezeboxrpc/issues\"\n },\n \"readmeFilename\": \"README.md\"\n}\n", "'use strict';\n/* globals $,window,document */\n/*\n var fontStyle = '12px \"Courier New\", monospace'\n var lineHeight = 15\n\n var picWidth = 50;\n var picHeight = 50;\n var test1 = \"Squeeze Work\";\n var test2 = \"SqueezeWork\";\n var test3 = \"aaa- aaa - aaa aaa aaa\";\n $('body').append(createTextImage(test1,fontStyle,picWidth,picHeight));\n */\n\n/**\n * Searches for the first occurrence of a given regular expression in the\n * string from the given start position. If the regex is not found, returns -1.\n *\n * @param regex The regular expression to search for\n * @param [startpos] The position to start the search from\n * @returns The position of the first match or -1 if not found\n */\nString.prototype.regexIndexOf = function (regex, startpos) {\n const indexOf = this.substring(startpos || 0).search(regex);\n return indexOf >= 0 ? indexOf + (startpos || 0) : indexOf;\n};\n\n/**\n * Wordwrap a given string, with options to wrap camel case words and set\n * the width of the output.\n *\n * @param str - The string to wordwrap\n * @param width - The width of the output\n * @param [opt] - Options object\n * @param [opt.wrapCamelCase] - Whether to wrap camel case words\n * @returns The wordwrapped string\n */\nfunction wordwrap(str, width, opt) {\n opt = opt || {};\n const splitChars = [' ', '-', '\\t'];\n if (opt.wrapCamelCase) {\n str = str.replace(/([a-z])([A-Z])/gm, '$1 $2');\n }\n const words = explode(str, splitChars);\n let curLineLength = 0;\n let strBuilder = '';\n for (let i = 0; i < words.length; i += 1) {\n let word = words[i];\n if (curLineLength + word.length > width) {\n if (curLineLength > 0) {\n strBuilder += '\\n';\n curLineLength = 0;\n }\n while (word.Length > width) {\n strBuilder += `${word.substring(0, width - 1)}-`;\n word = word.substring(width - 1);\n strBuilder += '\\n';\n }\n word = word.trimStart();\n }\n if (curLineLength == 0 && /^\\s+$/.test(word)) {\n word = word.trimStart();\n }\n strBuilder += word;\n curLineLength += word.length;\n }\n return strBuilder;\n}\n\n/**\n * Split a string into parts where each part is either a word or a whitespace/dash character.\n * If a whitespace/dash character occurs between two words, it is put into its own part.\n * If a whitespace/dash character occurs at the end of a word, it is put into the same part as the word.\n *\n * @param str The string to split.\n * @returns An array of string parts.\n */\nfunction explode(str) {\n const parts = [];\n let startIndex = 0;\n\n while (true) {\n const index = str.regexIndexOf(/[ |\\t|-]/gm, startIndex);\n if (index == -1) {\n parts.push(str.substring(startIndex));\n return parts;\n }\n const word = str.substring(startIndex, startIndex + index - startIndex);\n const nextChar = str.substring(index, index + 1)[0];\n\n // Dashes and the likes should stick to the word occuring before it. Whitespace doesn't have to.\n if (/^\\s+$/.test(nextChar)) {\n parts.push(word);\n parts.push(nextChar);\n } else {\n parts.push(word + nextChar);\n }\n startIndex = index + 1;\n }\n}\n\n/**\n * Calculates the height metrics of the text using the specified font.\n *\n * This function creates a temporary DOM structure to measure the ascent,\n * descent, and total height of the text \"Hg\" rendered with the given font.\n *\n * @param font - An object representing the font, which provides a method\n * to get the font string.\n * @returns An object containing the ascent, descent, and total height\n * of the text, with properties:\n * - ascent: The distance from the baseline to the top of the text.\n * - descent: The distance from the baseline to the bottom of the text.\n * - height: The total height of the text.\n */\nconst getTextHeight = function (font) {\n const text = $('<span>Hg</span>').css({ font: font.getfont() });\n const block = $('<div style=\"display: inline-block; width: 1px; height: 0px;\"></div>');\n\n const div = $('<div></div>');\n div.append(text, block);\n\n const body = $('body');\n body.append(div);\n const result = {};\n try {\n block.css({ verticalAlign: 'baseline' });\n result.ascent = block.offset().top - text.offset().top;\n\n block.css({ verticalAlign: 'bottom' });\n result.height = block.offset().top - text.offset().top;\n\n result.descent = result.height - result.ascent;\n } finally {\n div.remove();\n }\n return result;\n};\n/**\n * @param text - The text to measure.\n * @param font - The font to use when measuring the text.\n * @returns The width of the text.\n */\nexport function getTextWidth(text, font) {\n const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'));\n const context = canvas.getContext('2d');\n context.font = font.getfont();\n const metrics = context.measureText(text);\n return metrics.width;\n}\n\n/** Class representing a Font. */\nexport class Font {\n /**\n * Creates a Font object for the given element.\n *\n * @param elem the element to get the font string from\n */\n constructor(elem) {\n this.span = document.createElement('span');\n const fontstr = this.getFontString(elem[0]);\n this.span.style.font = fontstr;\n this.measure = getTextHeight(this);\n this.measure.width = getTextWidth('M', this);\n }\n /**\n * Retrieves the ascent value of the font.\n *\n * @returns {number} The ascent value of the font.\n */\n getAscent() {\n return this.measure.ascent;\n }\n /**\n * Retrieves the descent value of the font.\n *\n * @returns {number} The descent value of the font.\n */\n getDescent() {\n return this.measure.descent;\n }\n /**\n * Retrieves the width of the font.\n *\n * @returns {number} The width of the font.\n */\n getWidth() {\n return this.measure.width;\n }\n /**\n * Retrieves the height value of the font.\n *\n * @returns {number} The height value of the font.\n */\n getHeight() {\n return this.measure.height;\n }\n /**\n * Returns the current font string for the font.\n *\n * @returns The current font string.\n */\n getfont() {\n return this.span.style.font;\n }\n /**\n * Set the font string for the font.\n *\n * @param fontstr the new font string\n * @returns The Font object, to allow chaining.\n */\n setfont(fontstr) {\n this.span.style.font = fontstr;\n return this;\n }\n /**\n * Increase the font size of the font by one pixel.\n *\n * @returns The Font object, to allow chaining.\n */\n incFontSize() {\n this.span.style.fontSize = `${parseInt(this.span.style.fontSize) + 1}px`;\n return this;\n }\n /**\n * Decrease the font size of the font by one pixel.\n *\n * @returns The Font object, to allow chaining.\n */\n decFontSize() {\n this.span.style.fontSize = `${parseInt(this.span.style.fontSize) - 1}px`;\n return this;\n }\n /**\n * Given an element, returns the CSS font string for that element.\n *\n * @param elem - The element to get the font string for.\n * @returns The CSS font string, or 'normal 12px sans-serif' if no font style is set.\n */\n getFontString(elem) {\n const style = window.getComputedStyle(elem);\n let elementFont = style.getPropertyValue('font');\n\n if (elementFont) {\n return elementFont;\n }\n\n const fontStyle = style.getPropertyValue('font-style');\n const fontVariant = style.getPropertyValue('font-variant');\n const fontWeight = style.getPropertyValue('font-weight');\n const fontSize = style.getPropertyValue('font-size');\n const fontFamily = style.getPropertyValue('font-family');\n\n elementFont = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize} ${fontFamily}`.replace(/ +/g, ' ').trim();\n return elementFont ? elementFont : 'normal 12px sans-serif';\n }\n}\n\n/**\n * Returns the first visible background colour of an element or one of its\n * ancestors. This lets generated canvas images follow VIS widget styles as\n * well as user supplied global CSS.\n *\n * @param {HTMLElement} element element whose effective background is required\n * @param {string} fallback fallback colour when all ancestors are transparent\n * @returns {string} effective CSS background colour\n */\nexport function getEffectiveBackgroundColor(element, fallback = '#000000') {\n for (let current = element; current; current = current.parentElement) {\n const backgroundColor = window.getComputedStyle(current).backgroundColor;\n if (\n backgroundColor &&\n backgroundColor != 'transparent' &&\n backgroundColor != 'rgba(0, 0, 0, 0)' &&\n backgroundColor != 'rgba(0,0,0,0)'\n ) {\n return backgroundColor;\n }\n }\n return fallback;\n}\n\n/**\n * Keeps an explicitly customised colour, but replaces the legacy default with\n * the effective colour inherited from VIS/CSS.\n *\n * @param {string} configured configured widget colour\n * @param {string} legacyDefault legacy default value from the VIS template\n * @param {string} inherited effective colour inherited from the widget\n * @returns {string} colour to render\n */\nexport function resolveLegacyDefaultColor(configured, legacyDefault, inherited) {\n if (!configured || configured.toLowerCase() == legacyDefault.toLowerCase()) {\n return inherited;\n }\n return configured;\n}\n/**\n * Adjusts the font size to ensure that the given lines of text fit within the specified width.\n *\n * @param lines - An array of strings, each representing a line of text.\n * @param picWidth - The maximum width in pixels that the text should occupy.\n * @param font - An object representing the font, which has methods to increase and decrease font size.\n * @returns The adjusted font object with a size that fits the lines within the specified width.\n */\nfunction getGoodFontSize(lines, picWidth, font) {\n while (true) {\n const maxWidth = getMaxPixelWidth(lines, font);\n if (maxWidth > picWidth) {\n font.decFontSize();\n } else {\n return font;\n }\n }\n}\n/**\n * Create a canvas with the given lines, using the given font and dimensions,\n * but using a font size which will fit the text into the canvas.\n *\n * @param lines the lines of text to be rendered\n * @param font the font to use, or a string describing it\n * @param picWidth the width of the canvas\n * @param picHeight the height of the canvas\n * @param lineHeight the line height of the text\n * @param [opt] options, as follows:\n * @param [opt.style] css style to use for the canvas\n * @param [opt.style.direction] direction of text, either 'ltr' or 'rtl'\n * @param [opt.style.textAlign] text alignment, either 'start', 'end', 'left', 'right', or 'center'\n * @param [opt.style.color] color of the text\n * @param [opt.style.backgroundcolor] background color of the canvas\n * @returns the canvas element\n */\nfunction createCanvas(lines, font, picWidth, picHeight, lineHeight, opt) {\n opt = opt || {};\n const canvas = document.createElement('canvas');\n $('body').append(canvas);\n canvas.width = picWidth;\n canvas.height = picHeight;\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = opt.style ? opt.backgroundcolor : 'black';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.font = font.getfont();\n ctx.fillStyle = opt.style ? opt.style.color : 'white';\n ctx.textAlign = opt.style ? opt.style.textAlign : 'center';\n let x = 0;\n if (opt.style) {\n if (opt.style.direction == 'ltr') {\n if (opt.style.textAlign == 'start' || opt.style.textAlign == 'left') {\n x = 0;\n }\n if (opt.style.textAlign == 'end' || opt.style.textAlign == 'right') {\n x = picWidth;\n }\n if (opt.style.textAlign == 'center') {\n x = picWidth / 2;\n }\n }\n if (opt.style.direction == 'rtl') {\n if (opt.style.textAlign == 'end' || opt.style.textAlign == 'left') {\n x = 0;\n }\n if (opt.style.textAlign == 'start' || opt.style.textAlign == 'right') {\n x = picWidth;\n }\n if (opt.style.textAlign == 'center') {\n x = picWidth / 2;\n }\n }\n } else {\n x = picWidth / 2;\n }\n const y = font.getDescent() + Math.floor((picHeight - lines.length * lineHeight) / 2);\n ctx.textBaseline = 'top';\n for (let i = 0; i < lines.length; i++) {\n ctx.fillText(lines[i], x, y + i * lineHeight);\n }\n return canvas;\n}\n/**\n * Return the maximum number of characters in any line of the given array of\n * strings.\n *\n * @param lines an array of strings, each a line of text.\n * @returns the maximum number of characters in any line.\n */\nfunction getMaxChars(lines) {\n return lines.reduce(\n function (acc, cur) {\n return Math.max(acc, cur.length);\n }.bind(this),\n 0,\n );\n}\n/**\n * Return the maximum width in pixels of the given lines of text, using the\n * given font. The width is calculated by summing the widths of each line of\n * text.\n *\n * @param lines an array of strings, each a line of text.\n * @param font the font to use, or a string describing it.\n */\nfunction getMaxPixelWidth(lines, font) {\n return lines.reduce(\n function (acc, cur) {\n return Math.max(acc, getTextWidth(cur.trim(), font));\n }.bind(this),\n 0,\n );\n}\n\n/**\n * Create a canvas with the given text, using the given font and dimensions,\n * but using a font size which will fit the text into the canvas.\n *\n * @param text the text to be rendered\n * @param font the font to use, or a string describing it\n * @param picWidth the width of the canvas\n * @param picHeight the height of the canvas\n * @param [opt] options, as follows:\n * @param [opt.style] css style to use for the canvas\n * @param [opt.style.direction] direction of text, either 'ltr' or 'rtl'\n * @param [opt.style.textAlign] text alignment, either 'start', 'end', 'left', 'right', or 'center'\n * @param [opt.style.color] color of the text\n * @param [opt.style.backgroundcolor] background color of the canvas\n * @param [opt.wrapCamelCase] whether to wrap camel case words\n * @returns the canvas element\n */\nexport function createTextImage(text, font, picWidth, picHeight, opt) {\n opt = opt || {};\n font = typeof font == 'string' ? new Font(font) : font;\n const lineHeight = font.getHeight(); //getTextHeight(font).height;\n const charWidth = font.getWidth(); //getTextWidth(\"M\", font);\n const maxChars = picWidth / charWidth;\n let maxLines = picHeight / lineHeight - 1;\n maxLines = maxLines < 0 ? 1 : maxLines;\n let lines;\n if (picHeight >= picWidth) {\n for (\n let textWidth = 1;\n (lines = wordwrap(text, textWidth, opt).split('\\n')) && maxLines + 1 < lines.length;\n textWidth++\n ) {\n //count textWidth\n }\n } else {\n for (\n let textWidth = 1;\n (lines = wordwrap(text, textWidth, opt).split('\\n')) && getMaxChars(lines) < maxChars && lines.length > 1;\n textWidth++\n ) {\n /* empty */\n }\n }\n const goodFont = getGoodFontSize(lines, picWidth, font);\n return createCanvas(lines, goodFont, picWidth, picHeight, lineHeight, opt);\n}\n", "/* globals $,vis */\n'use strict';\n\nimport { parseRequestFactory } from '../sbClasses.js';\nimport { getTextWidth, Font } from '../textImage.js';\n\nexport const browser = {\n topitems: [\n {\n title: 'My Music',\n actions: JSON.stringify({ next: 'mymusic' }),\n id: 'myMusic',\n },\n {\n title: 'Radio',\n actions: JSON.stringify({ next: 'radio' }),\n id: 'radio',\n },\n {\n title: 'Favorites',\n actions: JSON.stringify({ next: 'favorites' }),\n id: 'favorites',\n },\n {\n title: 'Apps',\n actions: JSON.stringify({ next: 'apps' }),\n id: 'apps',\n },\n {\n title: 'Extra',\n actions: JSON.stringify({ next: 'extra' }),\n id: 'extra',\n },\n ],\n specialRangeHandling: [\n {\n mode: 'mode:floptracks',\n range: [0, 200],\n },\n {\n mode: 'mode:toptracks',\n range: [0, 200],\n },\n ],\n indexParam: [0, 25000],\n info: {},\n createWidget: async function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].browser.createWidget(widgetID, view, data, style);\n }, 100);\n }\n if (!this.info[widgetID]) {\n this.info[widgetID] = {\n history: [],\n data: data,\n style: style,\n view: view,\n };\n }\n vis.binds['squeezeboxrpc'].debug = data.debug || false;\n vis.binds['squeezeboxrpc'].fetchResults = data.debugwithFetchResults || false;\n\n this.info[widgetID].instance = data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes(\n $div,\n data.widgetPlayer,\n );\n let ainstance = this.info[widgetID].instance;\n if (!ainstance) {\n return;\n }\n const playername = await vis.binds['squeezeboxrpc'].getPlayerNameAsync(data.widgetPlayer);\n const state = `${ainstance[0]}.${ainstance[1]}.Players` + `.${playername}.PlayerID`;\n this.info[widgetID].playerid = await vis.binds['squeezeboxrpc'].getPlayerID(state);\n this.goDeeper(widgetID, { id: 'home', title: 'Home', params: null });\n },\n async goDeeper(widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`goDeeper ${widgetID}`);\n let children = await this.fetchChildren(widgetID, data);\n if (!children) {\n vis.binds['squeezeboxrpc'].debug && console.log(`End of tree reached ${widgetID}`);\n return;\n }\n this.info[widgetID].history.push(data);\n this.render(widgetID, children);\n },\n async goBack(widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`goBack ${widgetID}`);\n if (this.info[widgetID].history.length > 1) {\n this.info[widgetID].history.pop();\n }\n if (this.info[widgetID].history.length == 0) {\n return;\n }\n let data = this.info[widgetID].history[this.info[widgetID].history.length - 1];\n let children = await this.fetchChildren(widgetID, data);\n this.render(widgetID, children);\n },\n async fetchChildren(widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`fetchChildren ${widgetID}`);\n let items = {};\n switch (data.id || '') {\n case 'home':\n items = this.topitems;\n // // title = target.title;\n break;\n case 'radio':\n items = await vis.binds['squeezeboxrpc'].browser.browseradio(widgetID, data);\n break;\n case 'favorites':\n items = await vis.binds['squeezeboxrpc'].browser.browserfavorites(widgetID, data);\n break;\n case 'apps':\n items = await vis.binds['squeezeboxrpc'].browser.browseapps(widgetID, data);\n break;\n case 'myMusic':\n case 'extra':\n items = await vis.binds['squeezeboxrpc'].browser.browsemenu(widgetID, data);\n break;\n default:\n if (data.actions) {\n items = await vis.binds['squeezeboxrpc'].browser.browseparametermenu(widgetID, data);\n }\n break;\n }\n if (!items) {\n return;\n }\n return items.filter(el => el);\n },\n browseapps: async function (widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browseapps ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['myapps', 'items', 0, '25000', 'menu:1'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n browseradio: async function (widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browseradio ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['radios', 0, '25000', 'menu:radio'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n browserfavorites: async function (widgetID) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browserfavorites ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['favorites', 'items', 0, '25000', 'menu:favorites'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n browsemenu: async function (widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browsemenu ${widgetID}`);\n let ainstance = this.info[widgetID].instance;\n const data1 = {\n playerid: this.info[widgetID].playerid,\n cmdArray: ['menu', 'items', 0, '25000', 'direct:1'],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', data1);\n let filter = item => item.item.node === data.id;\n let menu = parseRequestFactory(request);\n return menu\n .getMenuItems()\n .filter(filter)\n .sort((a, b) => a.item.weight - b.item.weight);\n //return this.parseResult(request, filter, data.id);\n },\n browseparametermenu: async function (widgetID, data) {\n vis.binds['squeezeboxrpc'].debug && console.log(`browseparametermenu ${widgetID}`);\n let parameter = JSON.parse(data.actions)['next'];\n let ainstance = this.info[widgetID].instance;\n let range = [...this.indexParam];\n if (parameter.params) {\n this.specialRangeHandling.forEach(item => {\n if (parameter.params.includes(item.mode)) {\n range = item.range;\n }\n });\n } /* else {\n return;\n } */\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: [...parameter.command, ...range, ...parameter.params],\n };\n let request = await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n let menu = parseRequestFactory(request);\n return menu.getMenuItems();\n },\n clickhandler: async function (event, widgetID, func, id) {\n vis.binds['squeezeboxrpc'].debug && console.log(`clickhandler ${widgetID} ${func} ${id}`);\n let child;\n\n event.preventDefault();\n event.stopPropagation();\n if (id) {\n child = this.info[widgetID].currentChildren.find(c => c.id == id);\n }\n if (func == 'next') {\n /* if (!child.param) {\n return;\n } */\n await this.goDeeper(widgetID, child);\n } else if (func == 'back') {\n await this.goBack(widgetID);\n return;\n } else {\n await this.doAction(widgetID, child, func, id);\n return;\n }\n },\n doAction: async function (widgetID, child, func /* , id */) {\n vis.binds['squeezeboxrpc'].debug && console.log(`doAction`);\n let actions = JSON.parse(child.actions);\n let parameter = actions[func];\n let ainstance = this.info[widgetID].instance;\n const cmd = {\n playerid: this.info[widgetID].playerid,\n cmdArray: [...parameter.command, ...parameter.params],\n };\n /* let request = */ await vis.binds['squeezeboxrpc'].browsesendToAsync(ainstance.join('.'), 'cmdGeneral', cmd);\n },\n render(widgetID, children) {\n vis.binds['squeezeboxrpc'].debug && console.log(`render ${widgetID}`);\n let backTitle = '--';\n backTitle = this.info[widgetID].history.reduce((acc, val, i) => `${acc} ${i == 0 ? '' : '/'} ${val.title}`, '');\n const font = new Font($(`#${widgetID}`));\n let textwidth = getTextWidth(`...${backTitle}`, font);\n let widgetwidth = $(`#${widgetID}`).width();\n\n this.info[widgetID].currentChildren = children;\n let text = '';\n\n text += `\n <style>\n /* Grundlegendes Layout der Listen-Container */\n #${widgetID} .sqbrowser-list-container {\n width: 100%;\n // max-width: 600px; /* Beispiel: feste max-Breite */\n margin: 0 auto; /* zentriert auf der Seite */\n box-sizing: border-box;\n }\n #${widgetID} .sqbrowser-parent-directory {\n position: sticky; /* \"Klebt\" an einer definierten Position */\n top: 0; /* Fixiert oben im Container */\n padding: 0rem 0rem;\n z-index: 10; /* Damit sie auch oben bleibt, falls andere Elemente dar\u00FCberliegen k\u00F6nnten */\n border-bottom: 1px solid #ccc;\n /* background-color: black; */\n cursor: pointer;\n }\n #${widgetID} .sqbrowser-ellipsis {\n white-space: nowrap;\n text-overflow: ellipsis;\n direction: rtl;\n overflow: hidden;\n }\n #${widgetID} .sqbrowser-scrollable-area {\n /* Hier legen wir die H\u00F6he fest, ab der gescrollt werden soll */\n /* max-height: 300px; */ /* Beispiel: 300px */\n overflow-y: auto; /* Vertikales Scrollen bei \u00DCberlauf */\n padding: 0 0rem;\n }\n /* Einzelne List-Items */\n #${widgetID} .sqbrowser-list-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.2rem;\n margin: 0.2rem 0;\n // background-color: #f8f8f8;\n border: 1px solid #ccc;\n border-radius: 4px;\n z-index: 1;\n }\n\n #${widgetID} .sqbrowser-list-item[onclick] {\n cursor: pointer; /* signalisiert, dass klickbar ist */\n }\n\n /* Der Text-Bereich innerhalb eines List-Items */\n #${widgetID} .sqbrowser-list-item-content {\n flex: 1; /* soll den verf\u00FCgbaren Platz f\u00FCllen */\n margin-right: 1rem; /* Abstand zu den Buttons */\n white-space: nowrap; /* verhindert Zeilenumbruch */\n overflow: hidden; /* versteckt \u00FCberflie\u00DFenden Text */\n text-overflow: ellipsis; /* f\u00FCgt \u201E...\u201C ein, wenn Text nicht passt */\n }\n\n /* Button-Gruppe auf der rechten Seite */\n #${widgetID} .sqbrowser-button-group {\n display: flex;\n align-items: center;\n }\n\n /* Die Buttons selbst */\n #${widgetID} .sqbrowser-action-btn {\n margin-left: 0.2rem;\n padding: 0.1rem 0.2rem;\n cursor: pointer;\n border: 1px solid #666;\n background-color: #eee;\n border-radius: 3px;\n font-size: 1rem;\n }\n #${widgetID} svg:active { \n transform: scale(0.8, 0.8);\n transform-origin: 50% 50%;\n }\n\n /* Drei-Punkte-Button standardm\u00E4\u00DFig ausgeblendet, \n nur sichtbar werden, wenn nicht genug Platz f\u00FCr Button2 ist */\n #${widgetID} .sqbrowser-more-btn {\n display: none; /* wird per Media Query eingeblendet */\n }\n #${widgetID} .sqbrowser-btn-svg {\n width: 1rem;\n height: 1rem;\n margin: 0px 1px;\n cursor: pointer;\n }\n #${widgetID} .sqbrowser-btn-svg-action {\n border: 1px solid white;\n }\n #${widgetID} .sqbrowser-btn-svg-menu {\n display: inline-block;\n vertical-align: middle;\n height: fit-content;\n }\n </style>\n `;\n text += ` \n <div class=\"sqbrowser-list-container\">\n <div class=\"sqbrowser-parent-directory ${textwidth - 10 > widgetwidth ? 'sqbrowser-ellipsis' : ''}\" onclick=\"vis.binds.squeezeboxrpc.browser.clickhandler(event, '${widgetID}', 'back')\">\n <div class=\"sqbrowser-btn-svg sqbrowser-btn-svg-menu\">\n ${vis.binds['squeezeboxrpc'].svg.menuback}\n </div>\n <span>${backTitle}</span>\n </div>\n <div class=\"sqbrowser-scrollable-area\">\n `;\n for (let i = 0; i < children.length; i++) {\n let buttons;\n if (children[i].actions) {\n buttons = JSON.parse(children[i].actions);\n }\n let click = '';\n if (buttons && buttons.next) {\n click = children[i].actions\n ? `onclick=\"vis.binds.squeezeboxrpc.browser.clickhandler(event, '${widgetID}', 'next','${children[i].id}')\"`\n : ``;\n }\n text += /* html */ `\n <div\n class=\"sqbrowser-list-item\"\n ${click}\n >\n <div class=\"sqbrowser-list-item-content\">${children[i].title}</div>\n <div class=\"sqbrowser-button-group\">\n `;\n\n if (buttons) {\n let actions = [\n { id: 'next', svg: 'next' },\n { id: 'play', svg: 'play' },\n { id: 'add', svg: 'add' },\n ];\n for (let action = 0; action < actions.length; action++) {\n if (buttons[actions[action].id]) {\n text += `\n <div class=\"sqbrowser-btn-svg sqbrowser-btn-svg-action\" onclick=\"vis.binds.squeezeboxrpc.browser.clickhandler(event, '${widgetID}', '${actions[action].id}','${children[i].id}')\">\n ${vis.binds['squeezeboxrpc'].svg[actions[action].svg]}\n </div>\n `;\n }\n }\n }\n text += ` \n </div>\n </div>\n `;\n }\n text += /* html */ `\n </div></div>\n `;\n $(`#${widgetID}`).html(text);\n },\n parseResult: function (request, filter, rootmenu) {\n vis.binds['squeezeboxrpc'].debug && console.log(`parseResult`);\n let result = request.result;\n if (result.years_loop) {\n let items = result.years_loop;\n return items.map(item => {\n return {\n id: item.year,\n title: `${item.year}`,\n type: 'years',\n favorites_url: item.facorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.works_loop) {\n let items = result.works_loop;\n return items.map(item => {\n return {\n id: `work_id:${item.work_id}`,\n title: `${item.favorites_title}`,\n type: 'work',\n favorites_url: item.facorites_url,\n albumid: item.album_id,\n composer: item.composer,\n composer_id: item.composer_id,\n work: item.work,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.genres_loop) {\n let items = result.genres_loop;\n return items.map(item => {\n return {\n id: item.id,\n title: `${item.genre}`,\n type: 'genre',\n favorites_url: item.facorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.albums_loop) {\n let items = result.albums_loop;\n return items.map(item => {\n return {\n id: item.id,\n title: `${item.artist} / ${item.album} (${item.year})`,\n image: `/music/${item.artwork_track_id}/cover_300x300_f`,\n type: 'album',\n favorites_url: item.facorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.artists_loop) {\n let items = result.artists_loop;\n return items.map(item => {\n return {\n id: item.id,\n title: item.artist,\n image: `/imageproxy/mai/artist/${item.id}/image_300x300_f`,\n type: 'artist',\n favorites_url: item.favorites_url,\n rootmenu: rootmenu,\n };\n });\n }\n if (result.item_loop) {\n let items = result.item_loop;\n const style = result.window?.windowStyle || '';\n //=='icon_list'){\n if (filter) {\n items = items.filter(filter);\n }\n if (rootmenu == 'myMusic' && style == 'icon_list') {\n return items.map(item => {\n return {\n id: item.commonParams.track_id,\n type: 'track',\n title: item.text.replace('\\n', ' - '),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n if (rootmenu == 'myMusic' && (style == 'text_list' || style == 'home_menu')) {\n return items.map(item => {\n if (item.type == 'audio') {\n return {\n id: item.params.item_id,\n type: 'track',\n title: item.text.replace('\\n', ' - '),\n icon: null,\n rootmenu: rootmenu,\n };\n }\n if (item.type == 'playlist') {\n let cmd = {\n command: ['browselibrary', 'items'],\n params: ['menu:browselibrary', 'mode:bmf', ...this.object2Array(item.params)],\n };\n return {\n id: item.params.item_id,\n type: 'playlist',\n title: `(D) ${item.text.replace('\\n', ' - ')}`,\n param: JSON.stringify(cmd),\n icon: null,\n rootmenu: rootmenu,\n };\n }\n });\n }\n if (style == '' && rootmenu == 'myMusic') {\n items = items.sort((a, b) => a.weight - b.weight);\n return items.map(item => {\n return {\n id: item.id,\n type: 'menu',\n title: item.text,\n param: JSON.stringify(this.translateMyMusicParameters(item.actions.go)),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n if (style == '' && rootmenu == 'radio') {\n items = items.sort((a, b) => a.weight - b.weight);\n return items.map(item => {\n return {\n id: item.text,\n type: 'radio',\n title: item.text,\n param: JSON.stringify(this.translateMyMusicParameters(item.actions.go)),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n if (rootmenu == 'radio' && style == 'text_list') {\n return items.map(item => {\n return {\n id: item.text,\n type: 'radio',\n title: item.text.replace('\\n', ' - '),\n param: JSON.stringify(this.translateMyMusicParameters(item.actions.go)),\n icon: null,\n rootmenu: rootmenu,\n };\n });\n }\n if (rootmenu == 'radio' && style == 'icon_list') {\n return items.map(item => {\n return {\n id: item.params.item_id,\n type: 'track',\n title: item.text.replace('\\n', ' - '),\n icon: item.icon,\n rootmenu: rootmenu,\n };\n });\n }\n }\n },\n\n object2Array: function (obj) {\n return Object.keys(obj).map(function (key) {\n return `${key}:${obj[key]}`;\n });\n },\n};\n", "'use strict';\n\nfunction normalizeItem(item) {\n const id = String(item?.id || '').trim();\n return id\n ? {\n id,\n enabled: item.enabled !== false,\n text: String(item.text || ''),\n image: String(item.image || ''),\n }\n : null;\n}\n\n/**\n * Parse a persisted item configuration.\n *\n * @param value persisted value\n */\nexport function parseItemConfiguration(value) {\n if (!value) {\n return null;\n }\n try {\n const parsed = typeof value == 'string' ? JSON.parse(value) : value;\n if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.items)) {\n return null;\n }\n const items = [];\n parsed.items.forEach(item => {\n const normalized = normalizeItem(item);\n if (normalized && !items.some(existing => existing.id == normalized.id)) {\n items.push(normalized);\n }\n });\n return {\n version: 1,\n defaultId: String(parsed.defaultId || ''),\n items,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Serialize an item configuration for a VIS widget attribute.\n *\n * @param configuration item configuration\n */\nexport function serializeItemConfiguration(configuration) {\n return JSON.stringify({\n version: 1,\n defaultId: String(configuration.defaultId || ''),\n items: configuration.items.map(normalizeItem).filter(Boolean),\n });\n}\n\n/**\n * Merge saved items with currently discovered IDs without changing saved data.\n *\n * @param configuration saved configuration\n * @param discoveredItems currently available items\n */\nexport function mergeConfiguredItems(configuration, discoveredItems) {\n const discovered = new Map(\n discoveredItems\n .map(item => {\n const source = typeof item == 'string' ? { id: item } : item;\n const normalized = normalizeItem(source);\n return normalized ? { ...source, ...normalized } : null;\n })\n .filter(Boolean)\n .map(item => [item.id, item]),\n );\n const result = (configuration?.items || []).map(item => {\n const remote = discovered.get(item.id);\n discovered.delete(item.id);\n return {\n ...remote,\n ...item,\n discoveredImage: remote?.image || '',\n available: !!remote,\n };\n });\n discovered.forEach(item => result.push({ ...item, enabled: true, available: true }));\n return result;\n}\n\n/**\n * Return enabled and currently available items in their configured order.\n *\n * @param configuration saved configuration\n * @param discoveredItems currently available items\n */\nexport function visibleConfiguredItems(configuration, discoveredItems) {\n return mergeConfiguredItems(configuration, discoveredItems).filter(\n item => item.enabled !== false && item.available,\n );\n}\n\nfunction legacyList(value) {\n return String(value || '')\n .split(',')\n .map(item => item.trim())\n .filter(Boolean);\n}\n\n/**\n * Convert legacy positional Players settings in memory.\n *\n * @param data legacy widget data\n * @param playerNames discovered player names\n */\nexport function legacyPlayerConfiguration(data, playerNames) {\n const configuredIndices = legacyList(data.viewindex);\n const orderedIndices = configuredIndices.length ? configuredIndices : playerNames.map((_, index) => String(index));\n const enabled = new Set(orderedIndices);\n const items = [];\n orderedIndices.forEach(value => {\n const index = Number(value);\n if (\n Number.isInteger(index) &&\n playerNames[index] !== undefined &&\n !items.some(item => item.id == playerNames[index])\n ) {\n items.push({\n id: playerNames[index],\n enabled: true,\n text: String(data[`buttonsText${index + 1}`] || ''),\n image: String(data[`buttonsImage${index + 1}`] || ''),\n });\n }\n });\n playerNames.forEach((id, index) => {\n if (!items.some(item => item.id == id)) {\n items.push({\n id,\n enabled: !configuredIndices.length || enabled.has(String(index)),\n text: String(data[`buttonsText${index + 1}`] || ''),\n image: String(data[`buttonsImage${index + 1}`] || ''),\n });\n }\n });\n const defaultIndex = Number(data.defaultPlayer);\n const defaultId = playerNames[defaultIndex] || String(data.defaultPlayer || '') || items[0]?.id || '';\n return { version: 1, defaultId, items };\n}\n\n/**\n * Convert legacy Favorites settings in memory.\n *\n * @param data legacy widget data\n * @param favorites discovered favorites\n */\nexport function legacyFavoriteConfiguration(data, favorites) {\n const discoveredIds = favorites.map(favorite => favorite.id);\n const configuredIds = legacyList(data.viewindex);\n const orderedIds = configuredIds.length ? configuredIds : discoveredIds;\n const items = [];\n orderedIds.forEach((id, position) => {\n const favorite = favorites.find(item => item.id == id);\n if (favorite && !items.some(item => item.id == id)) {\n items.push({\n id,\n enabled: true,\n text: String(data[`buttonsText${position + 1}`] || ''),\n image: String(data[`buttonsImage${position + 1}`] || ''),\n });\n }\n });\n favorites.forEach(favorite => {\n if (!items.some(item => item.id == favorite.id)) {\n items.push({ id: favorite.id, enabled: false, text: '', image: '' });\n }\n });\n return { version: 1, defaultId: '', items };\n}\n\n/**\n * Return a reordered copy of the item list.\n *\n * @param items configured items\n * @param index source index\n * @param offset movement offset\n */\nexport function moveConfiguredItem(items, index, offset) {\n const target = index + offset;\n if (index < 0 || target < 0 || index >= items.length || target >= items.length) {\n return items;\n }\n const result = items.slice();\n const [item] = result.splice(index, 1);\n result.splice(target, 0, item);\n return result;\n}\n", "/* globals $,vis,window */\n'use strict';\n\nimport { createTextImage, Font } from '../textImage.js';\nimport { legacyFavoriteConfiguration, parseItemConfiguration, visibleConfiguredItems } from '../itemConfiguration.js';\n\nexport const favorites = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].favorites.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n // Keep the saved configuration and already resolved runtime bindings in\n // a mutable object. Resolved values must win over their raw expressions.\n data = { ...vis.views[view].widgets[widgetID].data, ...(data || {}) };\n style = vis.views[view].widgets[widgetID].style;\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n const key = `${ainstance[0]}.${ainstance[1]}.` + `Favorites.*`;\n vis.conn.gettingStates = 0;\n vis.conn.getStates(\n key,\n function (err, obj) {\n let favorites = this.getFavorites(obj, ainstance);\n favorites = this.filterFavorites(favorites);\n const configuration =\n parseItemConfiguration(data.favoriteConfiguration) || legacyFavoriteConfiguration(data, favorites);\n const configuredFavorites = visibleConfiguredItems(configuration, favorites);\n\n const editmodehelper = data.editmodehelper;\n const picWidth = data.picWidth;\n const picHeight = data.picHeight;\n const opacity = vis.editMode && editmodehelper ? 1 : data.opacity;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercolornormal = data.bordercolornormal;\n const bordercoloractive = data.bordercoloractive;\n const borderradius = data.borderradius;\n const buttonmargin = data.buttonmargin || '0px';\n\n let text = '';\n\n text += '<style>\\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += '}\\n';\n text += `#${widgetID} div div {\\n`;\n text += ' position: relative; \\n';\n text += ` margin: 0px ${buttonmargin} ${buttonmargin} 0px; \\n`;\n text += '}\\n';\n text += `#${widgetID} #${widgetID}container {\\n`;\n text += ' box-sizing: border-box;\\n';\n text += ' display: block;\\n';\n text += ' width: 100%;\\n';\n text += ' height: 100%;\\n';\n text += ' overflow: auto;\\n';\n text += ' scrollbar-width: thin;\\n';\n text += '}\\n';\n text += `#${widgetID} #${widgetID}container::-webkit-scrollbar {\\n`;\n text += ' width: 6px;\\n';\n text += ' height: 6px;\\n';\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"] {\\n`;\n text += ' display: none;\\n';\n text += '}\\n';\n text += `#${widgetID} img {\\n`;\n text += ` opacity: ${opacity};\\n`;\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornormal};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} canvas {\\n`;\n text += ` opacity: ${opacity};\\n`;\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornormal};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} img:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} canvas:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label img {\\n`;\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label canvas {\\n`;\n text += ' opacity: 1;\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += '}\\n';\n text += '</style>\\n';\n\n text += `<div id=\"${widgetID}container\">`;\n for (let i = 0; i < configuredFavorites.length; i++) {\n const favorite = configuredFavorites[i];\n text += ' <div>';\n text += ` <input type=\"radio\" id=\"${widgetID}${favorite.id}\" name=\"${widgetID}\" value=\"${\n favorite.id\n }\" >`;\n text += ` <label for=\"${widgetID}${favorite.id}\">`;\n text += ' <span>';\n let favimage = favorite.image || favorite.discoveredImage || '';\n let favtext = favorite.id || '';\n let attrimage = favorite.image || '';\n let attrtext = favorite.text || '';\n\n favimage = favimage.trim();\n favtext = favtext.trim();\n attrimage = attrimage.trim();\n attrtext = attrtext.trim();\n\n const buttonsImage = attrimage || favimage;\n\n if (!attrtext && buttonsImage) {\n text += ` <img src=\"${buttonsImage}\">`;\n }\n text += ' </span>';\n text += ' </label>';\n if (vis.editMode && editmodehelper) {\n text += `<div style=\"position: absolute;top: 0;right: 0;background-color: black;color: white;border-width: 1px;border-color: white;border-style: solid;font-size: xx-small;padding: 1px;\">${\n favorite.id\n }</div>`;\n }\n text += ' </div>';\n }\n text += '</div>';\n\n $(`#${widgetID}`).html(text);\n\n const spans = $(`#${widgetID} span`);\n const font = new Font($(`#${widgetID}`));\n const opt = {};\n const computedStyle = window.getComputedStyle($(`#${widgetID}`)[0], null);\n\n opt.style = {\n color: style?.color || '#ffffff',\n direction: computedStyle.direction,\n textAlign: computedStyle.textAlign || 'center',\n };\n opt.backgroundcolor = data.buttonbkcolor || '#000000';\n for (let i = 0; i < configuredFavorites.length; i++) {\n const favorite = configuredFavorites[i];\n\n let favimage = favorite.image || favorite.discoveredImage || '';\n let favtext = `${favorite.id || ''}(${i})`;\n let attrimage = favorite.image || '';\n let attrtext = favorite.text || favorite.name || '';\n\n favimage = favimage.trim();\n favtext = favtext.trim();\n attrimage = attrimage.trim();\n attrtext = attrtext.trim();\n\n const buttonsImage = attrimage || favimage;\n\n const buttonsText = attrtext || favtext;\n if (attrtext || !buttonsImage) {\n $(spans[i]).append(createTextImage(buttonsText, font, picWidth, picHeight, opt));\n }\n }\n const favbtns = $(`input[name=${widgetID}]`);\n favbtns.off('change.favorite').on('change.favorite', fdata, function (event) {\n const fdata = event.data;\n const data = fdata.data;\n const favorite = this.value;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const state = `${ainstance[0]}.${ainstance[1]}.Players` + `.${playername}.cmdPlayFavorite`;\n //vis.conn._socket.emit('setState', state, favorite);\n vis.setValue(state, favorite);\n });\n }.bind(this),\n );\n },\n getFavorites: function (datapoints, ainstance) {\n const regex = new RegExp(`^${ainstance[0]}\\\\.${ainstance[1]}\\\\.Favorites`, '');\n return Object.keys(datapoints).reduce(\n function (acc, cur) {\n if (regex.test(cur)) {\n const key = cur.split('.')[3];\n const name = cur.split('.')[4];\n if (!acc[key]) {\n acc[key] = {};\n }\n acc[key][name] = this[cur].val;\n }\n return acc;\n }.bind(datapoints),\n [],\n );\n },\n filterFavorites: function (favorites) {\n favorites = Object.values(favorites);\n return favorites.filter(function (cur) {\n return cur.isaudio === 1;\n });\n },\n};\n", "/* globals $,vis,window */\n'use strict';\n\nimport { createTextImage, Font, getEffectiveBackgroundColor, resolveLegacyDefaultColor } from '../textImage.js';\nimport { legacyPlayerConfiguration, parseItemConfiguration, visibleConfiguredItems } from '../itemConfiguration.js';\n\nexport const players = {\n createWidget: async function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].players.createWidget(widgetID, view, data, style);\n }, 100);\n }\n // VIS may expose the saved widget configuration as a frozen object, while\n // the data passed to the renderer contains already resolved bindings.\n // Keep both in a mutable copy and prefer the resolved runtime values.\n data = { ...vis.views[view].widgets[widgetID].data, ...(data || {}) };\n style = vis.views[view].widgets[widgetID].style;\n data.ainstance = data.ainstance ? data.ainstance.split('.').slice(0, 2).join('.') : '';\n const ainstance = data.ainstance.split('.');\n if (ainstance[0] != 'squeezeboxrpc' || !ainstance[1]) {\n $div.html('Please select an instance');\n return;\n }\n\n const renderPlayers = function (playerNames) {\n const configuration =\n parseItemConfiguration(data.playerConfiguration) || legacyPlayerConfiguration(data, playerNames);\n const configuredPlayers = visibleConfiguredItems(configuration, playerNames);\n\n const picWidth = data.picWidth;\n const picHeight = data.picHeight;\n const opacity = data.opacity;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercoloractive = data.bordercoloractive;\n const borderradius = data.borderradius;\n const buttonmargin = data.buttonmargin || '0px';\n\n const defaultPlayer = configuredPlayers.some(player => player.id == configuration.defaultId)\n ? configuration.defaultId\n : configuredPlayers[0]?.id || '';\n if (data.formattype == 'formatselect') {\n let text = '';\n let option = '';\n option += '<option value=\"\"></option>';\n for (let i = 0; i < configuredPlayers.length; i++) {\n const buttonsText = configuredPlayers[i].text || configuredPlayers[i].id;\n option += `<option value=\"${configuredPlayers[i].id}\" ${\n configuredPlayers[i].id == defaultPlayer ? 'selected' : ''\n }>${buttonsText}</option>`;\n }\n text += `<select type=\"text\" id=\"${widgetID}select\">${option}</select>`;\n $(`#${widgetID}`).html(text);\n }\n if (data.formattype == 'formatbutton') {\n const widgetElement = $div[0];\n const computedStyle = window.getComputedStyle(widgetElement, null);\n const foregroundColor = computedStyle.color || '#ffffff';\n const backgroundColor = resolveLegacyDefaultColor(\n data.buttonbkcolor,\n '#000000',\n getEffectiveBackgroundColor(widgetElement, '#000000'),\n );\n const bordercolornormal = data.bordercolornormal;\n\n let text = '';\n\n text += '<style>\\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += '}\\n';\n text += `#${widgetID} div div {\\n`;\n text += ' position: relative; \\n';\n text += ` margin: 0px ${buttonmargin} ${buttonmargin} 0px; \\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"] {\\n`;\n text += ' display: none;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span {\\n`;\n text += ' display: inline-block;\\n';\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornormal};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += ' overflow: hidden;\\n';\n text += ' vertical-align: top;\\n';\n text += '}\\n';\n text += `#${widgetID} img, #${widgetID} canvas {\\n`;\n text += ' display: block;\\n';\n text += ` opacity: ${opacity};\\n`;\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ' border: 0;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += '}\\n';\n text += `#${widgetID} label > span:active img, #${widgetID} label > span:active canvas {\\n`;\n text += ' opacity: 1;\\n';\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label > span {\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercoloractive};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"radio\"]:checked + label > span img,\\n`;\n text += `#${widgetID} input[type=\"radio\"]:checked + label > span canvas {\\n`;\n text += ' opacity: 1;\\n';\n text += '}\\n';\n text += '</style>\\n';\n\n text += `<div id=\"${widgetID}container\" >`;\n\n for (let i = 0; i < configuredPlayers.length; i++) {\n const player = configuredPlayers[i];\n text += ' <div >';\n text += ` <input type=\"radio\" id=\"${widgetID}${player.id}\" name=\"${widgetID}\" value=\"${player.id}\" ${\n player.id == defaultPlayer ? 'checked' : ''\n }>`;\n text += ` <label for=\"${widgetID}${player.id}\">`;\n text += ' <span>';\n const buttonsImage = player.image || '';\n if (buttonsImage.trim() != '') {\n text += ` <img src=\"${buttonsImage}\">`;\n }\n text += ' </span>';\n text += ' </label>';\n text += ' </div>';\n }\n text += '</div>';\n\n $(`#${widgetID}`).html(text);\n\n const spans = $(`#${widgetID} span`);\n const opt = {};\n opt.wrapCamelCase = data.wrapcamelcase;\n opt.style = {\n color: foregroundColor,\n direction: computedStyle.direction,\n textAlign: computedStyle.textAlign || 'center',\n };\n opt.backgroundcolor = backgroundColor;\n for (let i = 0; i < configuredPlayers.length; i++) {\n const font = new Font($(`#${widgetID}`));\n const buttonsImage = configuredPlayers[i].image || '';\n const buttonsText = configuredPlayers[i].text || configuredPlayers[i].id;\n if (buttonsImage.trim() == '') {\n $(spans[i]).append(createTextImage(buttonsText, font, picWidth, picHeight, opt));\n }\n }\n }\n $(`#${widgetID}`)\n .off('change.playerselection')\n .on('change.playerselection', () => vis.binds.squeezeboxrpc.publishPlayerSelection(widgetID));\n vis.binds.squeezeboxrpc.publishPlayerSelection(widgetID);\n $('body').trigger('squeezeboxrpcplayerschanged', [widgetID]);\n }.bind(this);\n\n try {\n const playerNames = await vis.binds['squeezeboxrpc'].sendToAsync(data.ainstance, 'getPlayerNames', {});\n if (!Array.isArray(playerNames)) {\n throw new TypeError(`Invalid getPlayerNames response: ${JSON.stringify(playerNames)}`);\n }\n renderPlayers(playerNames);\n } catch (error) {\n console.error(`Cannot read player names for ${data.ainstance}:`, error);\n $div.html('Cannot read players');\n }\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonplay = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonplay.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.state`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n this.setState(fdata);\n },\n onClick: function (event) {\n const data = event.data.data;\n const widgetID = event.data.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.state`;\n let state = $(`input[name=${widgetID}]`).val();\n state = state == 1 ? 0 : 1;\n vis.setValue(stateid, state);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const svg = vis.binds['squeezeboxrpc'].svg;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonplay.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.state`;\n\n const state =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0\n ? parseInt(vis.states[`${stateid}.val`])\n : 2;\n const imagepause = data.imagepause || '';\n const imageplay = data.imageplay || '';\n const imagestop = data.imagepause || '';\n\n let image = '';\n //0=pause\n //1=play\n //2=stop\n if (state == 0) {\n image = imageplay || svg.play;\n }\n if (state == 1) {\n image = imagepause || svg.pause;\n }\n if (state == 2) {\n image = imagestop || svg.play;\n }\n $(`#${widgetID} input`).val(state);\n $(`#${widgetID} img`).off('click.play', this.onClick);\n $(`#${widgetID} svg`).off('click.play', this.onClick);\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n $(`#${widgetID} img`).on('click.play', fdata, this.onClick);\n $(`#${widgetID} svg`).on('click.play', fdata, this.onClick);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonfwd = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonfwd.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const svg = vis.binds['squeezeboxrpc'].svg;\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"fwd\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n\n const image = data.imagefwd || svg.fwd;\n\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n\n //one onclick on span?\n $(`#${widgetID} img`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n $(`#${widgetID} svg`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.btnForward`;\n const state = true;\n vis.setValue(stateid, state);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonrew = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonrew.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const svg = vis.binds['squeezeboxrpc'].svg;\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"rew\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n\n const image = data.imagerew || svg.rew;\n\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n\n //one onclick on span?\n $(`#${widgetID} img`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n $(`#${widgetID} svg`).on(\n 'click',\n { self: this, widgetID: widgetID, view: view, data: data, style: style },\n this.onClick,\n );\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.btnRewind`;\n const state = true;\n vis.setValue(stateid, state);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\n/**\n * Normalize PlaylistRepeat to one of the three supported states.\n *\n * @param {string|number|undefined|null} value State value.\n */\nexport function normalizeRepeatState(value) {\n const state = Number.parseInt(String(value), 10);\n return state === 0 || state === 1 || state === 2 ? state : 0;\n}\n\n/**\n * Return the next PlaylistRepeat state.\n *\n * @param {string|number|undefined|null} value Current state value.\n */\nexport function nextRepeatState(value) {\n return (normalizeRepeatState(value) + 1) % 3;\n}\n\nexport const buttonrepeat = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonrepeat.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.PlaylistRepeat`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n this.setState({ self: this, widgetID: widgetID, view: view, data: data, style: style });\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return;\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistRepeat`;\n const state = vis.states[`${stateid}.val`];\n vis.setValue(stateid, nextRepeatState(state));\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const svg = vis.binds['squeezeboxrpc'].svg;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonrepeat.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistRepeat`;\n\n const state = normalizeRepeatState(vis.states[`${stateid}.val`]);\n const imagerepeat0 = data.imagerepeat0 || '';\n const imagerepeat1 = data.imagerepeat1 || '';\n const imagerepeat2 = data.imagerepeat2 || '';\n\n // 0 = repeat0 disabled, 1 = repeat1 enabled, 2 = custom repeat2 or repeat0 enabled\n const image =\n state === 1\n ? imagerepeat1 || svg.repeat1\n : state === 2\n ? imagerepeat2 || imagerepeat0 || svg.repeat0\n : imagerepeat0 || svg.repeat0;\n $(`#${widgetID} input`).val(state);\n $(`#${widgetID} img`).off('click.repeat', this.onClick);\n $(`#${widgetID} svg`).off('click.repeat', this.onClick);\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n }\n } else {\n $(`#${widgetID} span`).html(`<img src=\"${image}\">`);\n }\n $(`#${widgetID} img, #${widgetID} svg`).css('opacity', state === 0 ? '0.5' : '1');\n $(`#${widgetID} img`).on('click.repeat', fdata, this.onClick);\n $(`#${widgetID} svg`).on('click.repeat', fdata, this.onClick);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const buttonshuffle = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonshuffle.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n let text = '';\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.PlaylistShuffle`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n text += '<style> \\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} input[type=\"submit\"] { \\n`;\n text += ' display: none; \\n';\n text += '} \\n';\n text += `#${widgetID} img { \\n`;\n text += ' width: 100%; \\n';\n\n text += '} \\n';\n text += `#${widgetID} img:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += '} \\n';\n text += `#${widgetID} svg { \\n`;\n text += ' width: 100%; \\n';\n text += '} \\n';\n text += `#${widgetID} svg:active { \\n`;\n text += ' transform: scale(0.9, 0.9); \\n';\n text += ' transform-origin: 50% 50%; \\n';\n text += '} \\n';\n text += '</style> \\n';\n\n text += '<div class=\"btn\"> \\n';\n text += ' <div> \\n';\n text += ` <input type=\"submit\" id=\"${widgetID}button\" name=\"${widgetID}\" value=\"\" >`;\n text += ' <span> \\n';\n text += ' <img src=\"\"> \\n';\n text += ' </span> \\n';\n text += ' </div> \\n';\n text += '</div> \\n';\n\n $(`#${widgetID}`).html(text);\n this.setState({ self: this, widgetID: widgetID, view: view, data: data, style: style });\n },\n onClick: function (event) {\n const data = event.data.data;\n const widgetID = event.data.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistShuffle`;\n let state = $(`input[name=${widgetID}]`).val();\n state = state > 1 ? 0 : parseInt(state) + 1;\n vis.setValue(stateid, state);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const svg = vis.binds['squeezeboxrpc'].svg;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].buttonshuffle.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.PlaylistShuffle`;\n\n const state =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0\n ? parseInt(vis.states[`${stateid}.val`])\n : 0;\n const imageshuffle0 = data.imageshuffle0 || '';\n const imageshuffle1 = data.imageshuffle1 || '';\n const imageshuffle2 = data.imageshuffle2 || '';\n\n let image = '';\n //0=pause\n //1=play\n //2=stop\n if (state == 0) {\n image = imageshuffle0 || svg.shuffle0;\n }\n if (state == 1) {\n image = imageshuffle1 || svg.shuffle0;\n }\n if (state == 2) {\n image = imageshuffle2 || svg.shuffle2;\n }\n $(`#${widgetID} input`).val(state);\n $(`#${widgetID} img`).off('click.shuffle', this.onClick);\n $(`#${widgetID} svg`).off('click.shuffle', this.onClick);\n if (image.startsWith('<svg')) {\n $(`#${widgetID} span`).html(image);\n const $g = $(`#${widgetID} svg > g`);\n if ($g.length) {\n data.fillcolor && $g.attr('fill', data.fillcolor);\n data.strokecolor && $g.attr('stroke', data.strokecolor);\n data.strokewidth && $g.attr('stroke-width', data.strokewidth);\n if (state === 0) {\n $g.attr('opacity', '.5');\n } else {\n $g.attr('opacity', '1');\n }\n }\n } else {\n $(`#${widgetID} img`).attr('src', image);\n }\n $(`#${widgetID} img`).on('click.shuffle', fdata, this.onClick);\n $(`#${widgetID} svg`).on('click.shuffle', fdata, this.onClick);\n },\n};\n", "'use strict';\n\n/**\n * Convert a click position into an ioBroker volume value.\n *\n * @param {number} position Click position inside the bar.\n * @param {number} size Width or height of the bar.\n * @param {number} segments Number of displayed segments.\n * @param {string} calctype Calculation mode.\n * @param {boolean} reverse Whether the direction is reversed.\n * @returns {number} Volume between 0 and 100.\n */\nexport function calculateVolume(position, size, segments, calctype, reverse) {\n const safeSize = Number(size);\n const safeSegments = Math.max(2, Number.parseInt(segments, 10) || 2);\n if (!Number.isFinite(safeSize) || safeSize <= 0) {\n return 0;\n }\n\n let safePosition = Math.min(Math.max(Number(position) || 0, 0), safeSize);\n if (reverse) {\n safePosition = safeSize - safePosition;\n }\n\n if (calctype === 'exact') {\n return Math.round((safePosition / safeSize) * 100);\n }\n\n const segment = Math.min(Math.floor(safePosition / (safeSize / safeSegments)), safeSegments - 1);\n return Math.round((segment / (safeSegments - 1)) * 100);\n}\n\n/**\n * Calculate how many segments should be active for a volume value.\n *\n * @param {number} volume Volume between 0 and 100.\n * @param {number} segments Number of displayed segments.\n * @returns {number} Number of active segments.\n */\nexport function calculateActiveLevels(volume, segments) {\n const safeSegments = Math.max(2, Number.parseInt(segments, 10) || 2);\n const safeVolume = Math.min(Math.max(Number(volume) || 0, 0), 100);\n return Math.round(safeVolume / (100 / (safeSegments - 1))) + 1;\n}\n", "/* globals $,vis */\n'use strict';\n\nimport { calculateActiveLevels, calculateVolume } from '../volumeUtils.js';\n\nexport const volumebar = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].volumebar.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = {\n self: this,\n widgetID: widgetID,\n view: view,\n data: data,\n style: style,\n ainstance: ainstance,\n };\n //if ($('#' + data.widgetPlayer).length>0) this.playersChanged({data:fdata});\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.Volume`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n const calctype = data.calctype || 'segstep';\n const segments = data.segments || 11;\n const position = data.position || 'vertical';\n let segheight, segwidth;\n if (position == 'vertical') {\n segheight = data.segheight || '100%';\n segwidth = data.segwidth || '100%';\n } else {\n segheight = data.segheight || '100%';\n segwidth = data.segwidth || '20px';\n }\n const borderwidth = data.borderwidth || '1px';\n const bordercolornormal = data.bordercolornormal || '#909090';\n const bordercoloractive = data.bordercoloractive || '#87ceeb';\n const fillcolornormal = data.fillcolornormal || '#005000';\n const fillcoloractive = data.fillcoloractive || '#00ff00';\n const reverse = data.reverse || false;\n const margin = data.margin || '1px';\n\n data.calctype = calctype;\n data.segments = segments;\n data.position = position;\n\n data.segheight = segheight;\n data.segwidth = segwidth;\n data.borderwidth = borderwidth;\n data.bordercolornormal = bordercolornormal;\n data.bordercoloractive = bordercoloractive;\n data.fillcolornormal = fillcolornormal;\n data.fillcoloractive = fillcoloractive;\n data.reverse = reverse;\n data.margin = margin;\n\n let text = '';\n text += '<style> \\n';\n text += ` #${widgetID} .volume { \\n`;\n text += ' box-sizing: border-box; \\n';\n text += ' display: inline-block; \\n';\n text += ' font-size:0px; \\n';\n text += ' width: 100%; \\n';\n text += ' height: 100%; \\n';\n text += ' overflow: visible; \\n';\n if (position == 'horizontal') {\n text += ' white-space: nowrap; \\n';\n }\n text += ' } \\n';\n text += ` #${widgetID} .level { \\n`;\n text += ' box-sizing: border-box; \\n';\n text += ' display: inline-block; \\n';\n text += ` outline: ${borderwidth} solid ${bordercolornormal}; \\n`;\n if (position == 'horizontal') {\n text += ` height: calc(100% - ( 2 * ${margin} )); \\n`;\n text += ` width: calc((100% / ${segments}) - ( 2 * ${margin} )); \\n`;\n }\n if (position == 'vertical') {\n text += ` height: calc((100% / ${segments}) - ( 2 * ${margin} )); \\n`;\n text += ` width: calc(100% - ( 2 * ${margin} )); \\n`;\n }\n text += ` background-color: ${fillcolornormal}; \\n`;\n text += ` margin: ${margin}; \\n`;\n text += ' } \\n';\n text += ` #${widgetID} .active { \\n`;\n text += ` border-color: ${bordercoloractive}; \\n`;\n text += ` background-color: ${fillcoloractive}; \\n`;\n text += ' } \\n';\n text += '</style> \\n';\n\n text += '<div class=\"volume\"> \\n';\n for (let i = 0; i < segments; i++) {\n text += ` <div class=\"level\" value=\"${i}\"></div> \\n`;\n }\n text += '</div> \\n';\n $(`#${widgetID}`).html(text);\n $(`#${widgetID} div.volume`).off('click.volume').on('click.volume', fdata, this.onClick);\n this.setState(fdata);\n if (vis.editMode) {\n vis.inspectWidgets(view, view);\n }\n },\n onClick: function (event) {\n const offset = $(this).offset();\n const x = event.pageX - offset.left;\n const y = event.pageY - offset.top;\n\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.Volume`;\n\n const position = data.position == 'horizontal' ? x : y;\n const size = data.position == 'horizontal' ? this.clientWidth : this.clientHeight;\n const state = calculateVolume(position, size, data.segments, data.calctype, data.reverse);\n\n vis.binds['squeezeboxrpc'].volumebar.renderState(event.data, state);\n vis.setValue(stateid, state);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].volumebar.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.Volume`;\n let state =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0 ? vis.states[`${stateid}.val`] : 0;\n if (vis.editMode) {\n state = 50;\n }\n\n this.renderState(fdata, state);\n },\n renderState: function (fdata, state) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const reverse = data.reverse;\n const level = calculateActiveLevels(state, data.segments);\n const selector = reverse\n ? `#${widgetID} div.volume > div.level:nth-last-child(-n+${level})`\n : `#${widgetID} div.volume > div.level:nth-child(-n+${level})`;\n $(`#${widgetID} div.volume > div.level`).removeClass('active');\n $(selector).addClass('active');\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const syncgroup = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n // if nothing found => wait\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function (fdata) {\n const data = fdata.data;\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.PlayerID`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.SyncMaster`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.SyncSlaves`);\n }\n return boundstates;\n },\n function () {\n setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.createWidget(widgetID, view, data, style);\n }, 100);\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n if (vis.binds['squeezeboxrpc'].getPlayerWidgetType(view, data.widgetPlayer) == 'formatselect') {\n $div.html('Only Player formattype button is supported');\n return false;\n }\n\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n\n const dataplayer = vis.binds.squeezeboxrpc.getPlayerWidgetData(data.widgetPlayer);\n\n const picWidth = dataplayer.picWidth;\n const picHeight = dataplayer.picHeight;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercolornogroup = data.bordercolornogroup;\n const bordercolorowngroup = data.bordercolorowngroup;\n const bordercolorothergroup = data.bordercolorothergroup;\n const borderradius = data.borderradius;\n const buttonmargin = data.buttonmargin || '0px';\n\n let text = '';\n text += '<style>\\n';\n text += `#${widgetID} div {\\n`;\n text += ' display: inline-block; \\n';\n text += '}\\n';\n text += `#${widgetID} div div {\\n`;\n text += ' position: relative; \\n';\n text += ` margin: 0px ${buttonmargin} ${buttonmargin} 0px; \\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"checkbox\"] {\\n`;\n text += ' display: none;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span {\\n`;\n text += ' display: inline-block;\\n';\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolornogroup};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += ' overflow: hidden;\\n';\n text += ' vertical-align: top;\\n';\n text += '}\\n';\n text += `#${widgetID} canvas {\\n`;\n text += ' display: block;\\n';\n text += ' opacity: 1;\\n';\n text += ` width: ${picWidth}px;\\n`;\n text += ` height: ${picHeight}px;\\n`;\n text += ' border: 0;\\n';\n text += '}\\n';\n text += `#${widgetID} label > span:active {\\n`;\n text += ' transform: scale(0.9, 0.9);\\n';\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolorowngroup};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"checkbox\"]:checked + label > span {\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolorowngroup};\\n`;\n text += '}\\n';\n text += `#${widgetID} input[type=\"checkbox\"][othergroup=\"true\"] + label > span {\\n`;\n text += ` border: ${borderwidth} ${borderstyle} ${bordercolorothergroup};\\n`;\n text += '}\\n';\n text += '</style>\\n';\n\n text += `<div id=\"${widgetID}container\" >`;\n let valid = false;\n for (let i = 0; i < players.length; i++) {\n const stateid = `${data.ainstance.join('.')}.Players` + `.${players[i]}.PlayerID`;\n const playerid =\n vis.states[`${stateid}.val`] || vis.states[`${stateid}.val`] === 0 ? vis.states[`${stateid}.val`] : '';\n valid = valid || playerid;\n text += ' <div>';\n text += ` <input type=\"checkbox\" id=\"${widgetID}${players[i]}\" name=\"${widgetID}\" playername=\"${\n players[i]\n }\" value=\"${playerid}\" disabled>`;\n text += ` <label for=\"${widgetID}${players[i]}\">`;\n text += ' <span>';\n text += ' <canvas></canvas>';\n text += ' </span>';\n text += ' </label>';\n text += ' </div>';\n }\n if (!valid) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.createWidget(widgetID, view, data, style);\n }, 100);\n }\n text += '</div>';\n $(`#${widgetID}`).html(text);\n\n for (let i = 0; i < players.length; i++) {\n const source = $(`#${data.widgetPlayer} input[value=\"${players[i]}\"] + label span :first-child`)[0];\n const destination = $(`#${widgetID}${players[i]} + label span canvas`)[0];\n if (!source || !destination) {\n continue;\n }\n\n const drawPlayerImage = function () {\n const isCanvas = source.tagName == 'CANVAS';\n const width = isCanvas ? source.width : $(source).width() || source.naturalWidth || source.width;\n const height = isCanvas ? source.height : $(source).height() || source.naturalHeight || source.height;\n if (!width || !height) {\n return;\n }\n destination.width = width;\n destination.height = height;\n const context = destination.getContext('2d');\n if (isCanvas) {\n context.drawImage(source, 0, 0);\n } else {\n context.drawImage(source, 0, 0, width, height);\n }\n };\n\n if (source.tagName == 'IMG' && !source.complete) {\n $(source).one('load.syncgroup', drawPlayerImage);\n } else {\n drawPlayerImage();\n }\n }\n\n const syncgroupbtns = $(`input[name=${widgetID}]`);\n syncgroupbtns.off('change.syncgroup').on('change.syncgroup', fdata, function (event) {\n const fdata = event.data;\n const data = fdata.data;\n const self = fdata.self;\n const syncplayer = this.value;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const syncplayername = $(this).attr('playername');\n let stateid;\n if (syncplayer) {\n if (!$(this).prop('checked')) {\n stateid = `${ainstance[0]}.${ainstance[1]}.Players` + `.${syncplayername}.cmdGeneral`;\n vis.setValue(stateid, '\"sync\",\"-\"');\n } else {\n stateid = `${ainstance[0]}.${ainstance[1]}.Players` + `.${playername}.cmdGeneral`;\n vis.setValue(stateid, `\"sync\",\"${syncplayer}\"`);\n }\n }\n self.setState(fdata);\n });\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n const syncgroups = [];\n for (let ip = 0; ip < players.length; ip++) {\n const playername = players[ip];\n const stateid1 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncMaster`;\n const stateid2 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncSlaves`;\n const state1 =\n vis.states[`${stateid1}.val`] || vis.states[`${stateid1}.val`] === 0\n ? vis.states[`${stateid1}.val`]\n : '';\n const state2 =\n vis.states[`${stateid2}.val`] || vis.states[`${stateid2}.val`] === 0\n ? vis.states[`${stateid2}.val`]\n : '';\n let state = state1.split(',').concat(state2.split(','));\n state = state.filter(item => item != '');\n if (Array.isArray(state)) {\n if (\n !syncgroups.reduce(function (acc, val) {\n return state[0] == '' || state.length == 0 || acc || val.includes(state[0]);\n }, false)\n ) {\n syncgroups.push(state);\n }\n }\n }\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].syncgroup.setState(fdata);\n }, 100);\n }\n const stateid1 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncMaster`;\n const stateid2 = `${data.ainstance.join('.')}.Players` + `.${playername}.SyncSlaves`;\n const stateid3 = `${data.ainstance.join('.')}.Players` + `.${playername}.PlayerID`;\n const state1 =\n vis.states[`${stateid1}.val`] || vis.states[`${stateid1}.val`] === 0 ? vis.states[`${stateid1}.val`] : '';\n const state2 =\n vis.states[`${stateid2}.val`] || vis.states[`${stateid2}.val`] === 0 ? vis.states[`${stateid2}.val`] : '';\n const state3 =\n vis.states[`${stateid3}.val`] || vis.states[`${stateid3}.val`] === 0 ? vis.states[`${stateid3}.val`] : '';\n let owngroup = null;\n for (let i = 0; i < syncgroups.length; i++) {\n if (syncgroups[i].includes(state3)) {\n owngroup = i;\n break;\n }\n }\n let state = state1.split(',').concat(state2.split(','));\n state = state.filter(item => item != '');\n for (let ip = 0; ip < players.length; ip++) {\n const playerbutton = players[ip];\n const playerstateid = `${data.ainstance.join('.')}.Players` + `.${playerbutton}.PlayerID`;\n const playerid =\n vis.states[`${playerstateid}.val`] || vis.states[`${playerstateid}.val`] === 0\n ? vis.states[`${playerstateid}.val`]\n : '';\n let playergroup = null;\n for (let is = 0; is < syncgroups.length; is++) {\n if (syncgroups[is].includes(playerid)) {\n playergroup = is;\n break;\n }\n }\n\n const $btn = $(`input[id=${widgetID}${playerbutton}]`);\n if (state.includes(playerid) && playerid !== state3) {\n $btn.prop('checked', true);\n } else {\n $btn.prop('checked', false);\n }\n if (playerid == state3) {\n $btn.prop('disabled', true);\n } else {\n $btn.prop('disabled', false);\n }\n if (playergroup != null && playergroup != owngroup) {\n $btn.attr('othergroup', true);\n } else {\n $btn.attr('othergroup', false);\n }\n }\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const playtime = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playtime.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.Duration`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.Time`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.state`);\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.cmdGoTime`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n const mainbarcolor = data.mainbarcolor;\n const playtimebarcolor = data.playtimebarcolor;\n const borderwidth = data.borderwidth;\n const borderstyle = data.borderstyle;\n const bordercolor = data.bordercolor;\n const borderradius = data.borderradius;\n\n let text = '';\n text += '<style> \\n';\n text += `#${widgetID} .playtimemain {\\n`;\n text += ' width: 100%;\\n';\n text += ' height: 100%;\\n';\n text += ` background-color: ${mainbarcolor};\\n`;\n text += ` border: ${bordercolor} ${borderwidth} ${borderstyle};\\n`;\n text += ` border-radius: ${borderradius};\\n`;\n text += ' overflow: hidden;\\n';\n text += '}';\n\n text += `#${widgetID} .playtimebar {\\n`;\n text += ' height: 100%;\\n';\n text += ` background-color: ${playtimebarcolor};\\n`;\n text += '}\\n';\n text += '</style> \\n';\n\n text += '<div class=\"playtimemain\">\\n';\n text += ' <div class=\"playtimebar\"></div>\\n';\n text += '</div>\\n';\n\n $(`#${widgetID}`).html(text);\n $(`#${widgetID} div.playtimemain`).on('click.playtime', fdata, this.onClick);\n\n this.setState(fdata);\n },\n onClick: function (event) {\n const data = event.data.data;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n const stateid_duration = `${data.ainstance.join('.')}.Players` + `.${playername}.Duration`;\n const stateid_gotime = `${data.ainstance.join('.')}.Players` + `.${playername}.cmdGoTime`;\n\n const state_duration =\n vis.states[`${stateid_duration}.val`] || vis.states[`${stateid_duration}.val`] === 0\n ? parseInt(vis.states[`${stateid_duration}.val`])\n : 0;\n const clickx = event.offsetX;\n const width = $(this).width();\n\n const time = (clickx / width) * state_duration;\n if (time > state_duration) {\n return;\n }\n vis.setValue(stateid_gotime, time.toString());\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playtime.setState(fdata);\n }, 100);\n }\n const stateid_duration = `${data.ainstance.join('.')}.Players` + `.${playername}.Duration`;\n const stateid_state = `${data.ainstance.join('.')}.Players` + `.${playername}.state`;\n const stateid_time = `${data.ainstance.join('.')}.Players` + `.${playername}.Time`;\n\n const state_duration =\n vis.states[`${stateid_duration}.val`] || vis.states[`${stateid_duration}.val`] === 0\n ? parseInt(vis.states[`${stateid_duration}.val`])\n : 0;\n const state_state =\n vis.states[`${stateid_state}.val`] || vis.states[`${stateid_state}.val`] === 0\n ? parseInt(vis.states[`${stateid_state}.val`])\n : 0;\n const state_time =\n vis.states[`${stateid_time}.val`] || vis.states[`${stateid_time}.val`] === 0\n ? parseInt(vis.states[`${stateid_time}.val`])\n : 0;\n\n let width = state_duration == 0 ? 0 : $(`#${widgetID} div.playtimebar`).width();\n if (state_state == 2) {\n width = 0;\n } //0 if player stop\n if (vis.editMode) {\n width = 50;\n } else if (state_duration <= 0) {\n width = 0;\n } else {\n width = Math.floor((state_time / state_duration) * 100);\n }\n $(`#${widgetID} div.playtimebar`).width(`${width}%`);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const string = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].string.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].string.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n const state = vis.states[`${stateid}.val`] ? vis.states[`${stateid}.val`] : '';\n //if (vis.editMode) state = data.test_html || \"\";\n const html_prepend = data.html_prepend || '';\n const html_append = data.html_append || '';\n $(`#${widgetID}`).html(html_prepend + state + html_append);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const playlist = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playlist.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: async function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const $div = $(`#${widgetID}`);\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].playlist.setState(fdata);\n }, 100);\n }\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n let result = await vis.binds['squeezeboxrpc'].getPlaylistData(ainstance.join('.'));\n let playlist = result.result.playlists_loop;\n let text = '';\n text += `\n <style>\n #${widgetID} ul.plcontainer {\n list-style-type: none;\n padding-left: 0px;\n margin: 0px;\n }\n #${widgetID} li.plentry {\n cursor: pointer;\n height: 1em;\n margin: 5px 0px;\n }\n #${widgetID} li.plentry div {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n #${widgetID} li.plrefresh {\n width: 1em;\n height: 1em;\n margin: 5px 0px;\n }\n </style>\n `;\n text += '<ul class=\"plcontainer\">';\n text +=\n '<li class=\"plrefresh\"><div><svg focusable=\"false\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" data-testid=\"RefreshIcon\"><path fill=\"currentColor\" d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4z\"></path></svg></div></li>';\n for (let i = 0; i < playlist.length; i++) {\n let pl = playlist[i];\n text += `<li class=\"plentry\"><div class=\"pltext\" data-plid=\"${pl.id}\" data-pln=\"${playername}\" data-ins=\"${ainstance.join('.')}\" onclick=\"vis.binds.squeezeboxrpc.playlist.onclickplaylist(this,event)\">${pl.playlist}</div></li>`;\n }\n text += '</ul>';\n $(`#${widgetID}`).html(text);\n $(`#${widgetID} li.refresh`).click(\n function (fdata) {\n vis.binds.squeezeboxrpc.playlist.setState(fdata);\n }.bind(this, fdata),\n );\n },\n onclickplaylist: function (el) {\n const playlistid = el.dataset.plid || '';\n const playername = el.dataset.pln || '';\n const instance = el.dataset.ins || '';\n const stateid = `${instance}.Players` + `.${playername}.cmdGeneral`;\n vis.setValue(stateid, `\"playlistcontrol\",\"cmd:load\",\"playlist_id:${playlistid}\"`);\n },\n onclickrefresh: function (el) {\n const playlistid = el.dataset.plid || '';\n const playername = el.dataset.pln || '';\n const instance = el.dataset.ins || '';\n const stateid = `${instance}.Players` + `.${playername}.cmdGeneral`;\n vis.setValue(stateid, `\"playlistcontrol\",\"cmd:load\",\"playlist_id:${playlistid}\"`);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\n/**\n * Normalize the Playlist state value for rendering.\n *\n * @param {unknown} value Playlist state value\n */\nexport function parsePlaylistDetail(value) {\n let entries = value;\n if (typeof value === 'string') {\n try {\n entries = JSON.parse(value);\n } catch {\n return [];\n }\n }\n if (!Array.isArray(entries)) {\n return [];\n }\n return entries.map((entry, position) => ({\n index: Number.isInteger(Number(entry?.index)) ? Number(entry.index) : position,\n id: String(entry?.id ?? position),\n title: String(entry?.title || ''),\n artworkUrl: String(entry?.ArtworkUrl || ''),\n artist: String(entry?.Artist || ''),\n album: String(entry?.Album || ''),\n duration: Number(entry?.Duration),\n }));\n}\n\n/**\n * Format a track duration like the VIS-2 widget.\n *\n * @param {unknown} value Duration in seconds\n */\nexport function formatPlaylistDuration(value) {\n const seconds = Number(value);\n if (!Number.isFinite(seconds) || seconds < 0) {\n return '--:--';\n }\n const totalSeconds = Math.floor(seconds);\n if (totalSeconds > 99 * 3600 + 59 * 60 + 59) {\n return '>99:59:59';\n }\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const remainingSeconds = totalSeconds % 60;\n const pad = number => String(number).padStart(2, '0');\n return hours\n ? `${pad(hours)}:${pad(minutes)}:${pad(remainingSeconds)}`\n : `${pad(minutes)}:${pad(remainingSeconds)}`;\n}\n\nfunction escapeHtml(value) {\n return String(value)\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\n\nfunction cssLength(value, fallback) {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return `${value}px`;\n }\n const text = String(value || fallback).trim();\n if (/^\\d+(?:\\.\\d+)?$/.test(text)) {\n return `${text}px`;\n }\n return /^\\d+(?:\\.\\d+)?(?:px|em|rem|%)$/.test(text) ? text : fallback;\n}\n\nexport const playlistdetail = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(\n () => vis.binds.squeezeboxrpc.playlistdetail.createWidget(widgetID, view, data, style),\n 100,\n );\n }\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n const ainstance = (data.ainstance = vis.binds.squeezeboxrpc.checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n const fdata = { self: this, widgetID, view, data, style };\n vis.binds.squeezeboxrpc.setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n () => {\n const states = [];\n for (const player of vis.binds.squeezeboxrpc.getPlayerValues(data.widgetPlayer)) {\n states.push(`${ainstance.join('.')}.Players.${player}.Playlist`);\n states.push(`${ainstance.join('.')}.Players.${player}.PlaylistCurrentIndex`);\n }\n return states;\n },\n this.setState.bind(fdata),\n );\n vis.binds.squeezeboxrpc.setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const { data, widgetID } = fdata;\n const previousScrollTop = $(`#${widgetID} .squeezeboxrpc-playlist-detail`).scrollTop() || 0;\n const player = vis.binds.squeezeboxrpc.getPlayerName(data.widgetPlayer);\n if (!player) {\n return setTimeout(() => vis.binds.squeezeboxrpc.playlistdetail.setState(fdata), 100);\n }\n const base = `${data.ainstance.join('.')}.Players.${player}`;\n const entries = parsePlaylistDetail(vis.states[`${base}.Playlist.val`]);\n const currentIndex = Number(vis.states[`${base}.PlaylistCurrentIndex.val`]);\n const showThumbnail = data.showThumbnail !== false && data.showThumbnail !== 'false';\n const showIndex = data.showIndex !== false && data.showIndex !== 'false';\n const rowBackground = data.rowBackground || '#f5f7fa';\n const activeBackground = data.activeRowBackground || '#dbeafe';\n const border = `${cssLength(data.rowBorderWidth, '1px')} ${data.rowBorderStyle || 'solid'} ${data.rowBorderColor || '#cbd5e1'}`;\n const spacing = cssLength(data.rowSpacing, '4px');\n let html = `<div class=\"squeezeboxrpc-playlist-detail\" style=\"--pl-row-background:${escapeHtml(rowBackground)};--pl-active-background:${escapeHtml(activeBackground)};--pl-row-border:${escapeHtml(border)};--pl-row-spacing:${escapeHtml(spacing)}\">`;\n for (const entry of entries) {\n const title = showIndex ? `${entry.index + 1}. ${entry.title}` : entry.title;\n const active = entry.index === currentIndex ? ' active' : '';\n html += `<div class=\"squeezeboxrpc-playlist-detail-row${active}${showThumbnail ? '' : ' no-thumbnail'}\">`;\n if (showThumbnail) {\n html += `<div>${entry.artworkUrl ? `<img class=\"squeezeboxrpc-playlist-detail-thumbnail\" src=\"${escapeHtml(entry.artworkUrl)}\" alt=\"\">` : ''}</div>`;\n }\n html += `<div class=\"squeezeboxrpc-playlist-detail-text\"><div class=\"squeezeboxrpc-playlist-detail-line squeezeboxrpc-playlist-detail-title\" title=\"${escapeHtml(title)}\">${escapeHtml(title)}</div><div class=\"squeezeboxrpc-playlist-detail-line\" title=\"${escapeHtml(entry.artist)}\">${escapeHtml(entry.artist)}</div><div class=\"squeezeboxrpc-playlist-detail-line\" title=\"${escapeHtml(entry.album)}\">${escapeHtml(entry.album)}</div></div>`;\n html += `<div class=\"squeezeboxrpc-playlist-detail-actions\"><span class=\"squeezeboxrpc-playlist-detail-duration\">${formatPlaylistDuration(entry.duration)}</span><div class=\"squeezeboxrpc-playlist-detail-buttons\"><button type=\"button\" class=\"squeezeboxrpc-playlist-detail-button play\" data-index=\"${entry.index}\" title=\"Play\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M8 5v14l11-7z\"/></svg></button><button type=\"button\" class=\"squeezeboxrpc-playlist-detail-button delete\" data-index=\"${entry.index}\" title=\"Delete\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM8 9h8v10H8V9zm7.5-5-1-1h-5l-1 1H5v2h14V4z\"/></svg></button></div></div></div>`;\n }\n html += '</div>';\n const $widget = $(`#${widgetID}`).html(html);\n $widget.find('.squeezeboxrpc-playlist-detail').scrollTop(previousScrollTop);\n $widget.off('.playlistdetail');\n $widget.on('click.playlistdetail', '.squeezeboxrpc-playlist-detail-button.play', event => {\n vis.setValue(`${base}.PlaylistCurrentIndex`, String(event.currentTarget.dataset.index));\n });\n $widget.on('click.playlistdetail', '.squeezeboxrpc-playlist-detail-button.delete', event => {\n vis.setValue(`${base}.cmdGeneral`, `\"playlist\",\"delete\",\"${Number(event.currentTarget.dataset.index)}\"`);\n });\n $widget.on('error.playlistdetail', '.squeezeboxrpc-playlist-detail-thumbnail', event => {\n event.currentTarget.style.visibility = 'hidden';\n });\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const number = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].number.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].number.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n let state = vis.states[`${stateid}.val`] ? vis.states[`${stateid}.val`] : '';\n // if (vis.editMode) state = data.test_html || \"\";\n state = parseFloat(state);\n if (state === undefined || state === null || isNaN(state)) {\n state = 0;\n }\n if (data.digits || data.digits !== '') {\n state = state.toFixed(parseFloat(data.digits, 10));\n }\n if (data.is_tdp && data.is_tdp !== '') {\n state = state.toString().split('.');\n state[0] = state[0].replace(/\\d{1,3}(?=(\\d{3})+(?!\\d))/g, '$&,');\n state = state.join('.');\n }\n if (data.is_comma && data.is_comma !== '') {\n state = state\n .split('.')\n .map(e => e.replace(/,/g, '.'))\n .join(',');\n }\n\n const html_prepend = data.html_prepend || '';\n const html_append = data.html_append || '';\n $(`#${widgetID}`).html(html_prepend + state + html_append);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\n/**\n * Format a player value with the same contract as the VIS-2 DateTime widget.\n *\n * @param {unknown} value Player state value\n * @param {unknown} factor Multiplier for the state value\n * @param {unknown} format Date/time format\n * @returns {string} Formatted value\n */\nexport function formatDateTime(value, factor, format) {\n const numericValue = Number(value);\n if (!Number.isFinite(numericValue)) {\n return '';\n }\n const multiplier = factor !== undefined && factor !== '' ? Number(factor) : 1;\n const offset = 60_000 * new Date(0).getTimezoneOffset();\n const date = new Date(numericValue * (Number.isFinite(multiplier) ? multiplier : 1) + offset);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n const pad = number => String(number).padStart(2, '0');\n const replacements = {\n YYYY: String(date.getFullYear()),\n YY: String(date.getFullYear()).slice(-2),\n MM: pad(date.getMonth() + 1),\n DD: pad(date.getDate()),\n hh: pad(date.getHours()),\n mm: pad(date.getMinutes()),\n ss: pad(date.getSeconds()),\n };\n return String(format || 'hh:mm:ss').replace(/YYYY|YY|MM|DD|hh|mm|ss/g, token => replacements[token]);\n}\n\nexport const datetime = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].datetime.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].datetime.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n const state = formatDateTime(vis.states[`${stateid}.val`], data.factor, data.format);\n const html_prepend = data.html_prepend || '';\n const html_append = data.html_append || '';\n $(`#${widgetID}`).html(html_prepend + state + html_append);\n },\n};\n", "/* globals $,vis */\n'use strict';\n\nexport const image = {\n createWidget: function (widgetID, view, data, style) {\n const $div = $(`#${widgetID}`);\n if (!$div.length) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].image.createWidget(widgetID, view, data, style);\n }, 100);\n }\n\n data = vis.views[view].widgets[widgetID].data;\n style = vis.views[view].widgets[widgetID].style;\n\n const ainstance = (data.ainstance = vis.binds['squeezeboxrpc'].checkAttributes($div, data.widgetPlayer));\n if (!ainstance) {\n return;\n }\n\n const fdata = { self: this, widgetID: widgetID, view: view, data: data, style: style };\n\n vis.binds['squeezeboxrpc'].setPlayersChanged(\n $div,\n data.widgetPlayer,\n fdata,\n this.onChange.bind(fdata),\n function () {\n const boundstates = [];\n const players = vis.binds['squeezeboxrpc'].getPlayerValues(data.widgetPlayer);\n for (let i = 0; i < players.length; i++) {\n boundstates.push(`${ainstance[0]}.${ainstance[1]}.Players.${players[i]}.${data.playerattribute}`);\n }\n return boundstates;\n },\n );\n vis.binds['squeezeboxrpc'].setChanged(data.widgetPlayer, fdata, this.setState.bind(fdata));\n let imgstyle = 'width:100%;';\n if (data.stretch) {\n imgstyle += 'height:100%;';\n }\n let text = '';\n text += data.html_prepend || '';\n text += `<img style=\"${imgstyle}\"></img> \\n`;\n text += data.html_append || '';\n $(`#${widgetID}`).html(text);\n this.setState(fdata);\n },\n onChange: function () {\n this.self.setState(this);\n },\n setState: function (fdata) {\n const data = fdata.data;\n const widgetID = fdata.widgetID;\n const playername = vis.binds['squeezeboxrpc'].getPlayerName(data.widgetPlayer);\n if (!playername) {\n return setTimeout(function () {\n vis.binds['squeezeboxrpc'].image.setState(fdata);\n }, 100);\n }\n const stateid = `${data.ainstance.join('.')}.Players` + `.${playername}.${data.playerattribute}`;\n\n const state = vis.states[`${stateid}.val`] ? vis.states[`${stateid}.val`] : '';\n // if (vis.editMode) state = data.test_html || \"\";\n $(`#${widgetID} img`).attr('src', state);\n },\n};\n", "/* globals $,vis,document */\n'use strict';\n\nimport {\n legacyFavoriteConfiguration,\n legacyPlayerConfiguration,\n mergeConfiguredItems,\n moveConfiguredItem,\n parseItemConfiguration,\n serializeItemConfiguration,\n} from './itemConfiguration.js';\n\nfunction editorContext(input) {\n const wdata = $(input).data('wdata');\n const widgetID = wdata?.widgets?.[0];\n const data = widgetID && vis.views[wdata.view]?.widgets?.[widgetID]?.data;\n return data ? { data, widgetID } : null;\n}\n\nfunction playerWidgetData(widgetID) {\n if (vis.widgets?.[widgetID]?.data) {\n return vis.widgets[widgetID].data;\n }\n for (const view of Object.values(vis.views || {})) {\n if (view.widgets?.[widgetID]?.data) {\n return view.widgets[widgetID].data;\n }\n }\n return null;\n}\n\nfunction playerInstance(data) {\n const value = String(data?.ainstance || '');\n const match = value.match(/(?:system\\.adapter\\.)?(squeezeboxrpc\\.\\d+)/);\n return match ? match[1] : '';\n}\n\nfunction getStates(pattern) {\n return new Promise((resolve, reject) => {\n vis.conn.getStates(pattern, (error, states) => (error ? reject(error) : resolve(states || {})));\n });\n}\n\nasync function discover(mode, data) {\n if (mode == 'players') {\n const instance = playerInstance(data);\n if (!instance) {\n throw new Error('Please select an instance first');\n }\n const names = await vis.binds['squeezeboxrpc'].sendToAsync(instance, 'getPlayerNames', {});\n if (!Array.isArray(names)) {\n throw new TypeError('Invalid getPlayerNames response');\n }\n return names.map(id => ({ id }));\n }\n\n const referencedPlayer = playerWidgetData(data.widgetPlayer);\n const instance = playerInstance(referencedPlayer);\n if (!instance) {\n throw new Error('Please select a Players widget first');\n }\n const states = await getStates(`${instance}.Favorites.*`);\n return vis.binds['squeezeboxrpc'].favorites\n .filterFavorites(vis.binds['squeezeboxrpc'].favorites.getFavorites(states, instance.split('.')))\n .map(favorite => ({\n id: favorite.id,\n name: favorite.Name || favorite.name || '',\n image: favorite.image || '',\n }));\n}\n\nfunction makeButton(text, title, action, disabled) {\n return $('<button type=\"button\"></button>')\n .text(text)\n .attr('title', title)\n .attr('data-action', action)\n .prop('disabled', disabled);\n}\n\nfunction selectImage(state, index) {\n const item = state.items[index];\n if (!item || !$.fm) {\n return;\n }\n const defaultPath = `/${vis.conn.namespace ? `${vis.conn.namespace}/` : ''}${vis.projectPrefix}img/`;\n $.fm(\n {\n lang: vis.language,\n defaultPath,\n path: item.image || defaultPath,\n uploadDir: `/${vis.conn.namespace ? `${vis.conn.namespace}/` : ''}`,\n fileFilter: ['gif', 'png', 'bmp', 'jpg', 'jpeg', 'tif', 'svg'],\n folderFilter: false,\n mode: 'open',\n view: 'prev',\n conn: vis.conn,\n zindex: 1001,\n },\n selected => {\n item.image = selected.path + selected.file;\n renderEditor(state);\n },\n );\n}\n\nfunction renderEditor(state) {\n const $editor = state.editor.empty();\n const $toolbar = $('<div style=\"display:flex;gap:4px;margin-bottom:6px\"></div>');\n $toolbar.append(makeButton('Refresh', 'Reload available entries', 'refresh', false));\n $toolbar.append(makeButton('Apply', 'Save this configuration', 'apply', false));\n $editor.append($toolbar);\n\n if (state.message) {\n $editor.append($('<div style=\"margin:4px 0;color:#b26a00\"></div>').text(state.message));\n }\n\n const $list = $('<div style=\"display:flex;flex-direction:column;gap:4px\"></div>');\n state.items.forEach((item, index) => {\n const $row = $(\n '<div style=\"display:grid;grid-template-columns:auto minmax(90px,1fr) auto auto;gap:4px;align-items:center;border:1px solid #aaa;padding:4px\"></div>',\n );\n const $enabled = $('<input type=\"checkbox\" data-action=\"enabled\">').prop('checked', item.enabled !== false);\n const label = item.name ? `${item.id} - ${item.name}` : item.id;\n const $name = $('<span style=\"overflow:hidden;text-overflow:ellipsis;white-space:nowrap\"></span>')\n .text(item.available === false ? `${label} (unavailable)` : label)\n .attr('title', label);\n $row.attr('data-index', index).append($enabled, $name);\n $row.append(makeButton('Up', 'Move up', 'up', index == 0));\n $row.append(makeButton('Down', 'Move down', 'down', index == state.items.length - 1));\n\n if (state.mode == 'players') {\n const $default = $('<label style=\"grid-column:1 / -1\"></label>');\n $default.append(\n $('<input type=\"radio\" name=\"squeezeboxrpc-default-player\" data-action=\"default\">').prop(\n 'checked',\n state.defaultId == item.id,\n ),\n document.createTextNode(' Default player'),\n );\n $row.append($default);\n }\n $row.append(\n $(\n '<input type=\"text\" data-action=\"text\" placeholder=\"Optional button text\" style=\"grid-column:1 / -1;width:100%;box-sizing:border-box\">',\n ).val(item.text),\n );\n $row.append(\n $(\n '<input type=\"text\" data-action=\"image\" placeholder=\"Optional image URL\" style=\"grid-column:1 / -2;width:100%;box-sizing:border-box\">',\n ).val(item.image),\n );\n $row.append(makeButton('Select', 'Select image', 'image-select', false));\n $list.append($row);\n });\n $editor.append($list);\n}\n\nasync function refreshEditor(state) {\n state.message = 'Loading...';\n renderEditor(state);\n try {\n const discovered = await discover(state.mode, state.data);\n const saved = parseItemConfiguration(state.input.value);\n const legacy =\n state.mode == 'players'\n ? legacyPlayerConfiguration(\n state.data,\n discovered.map(item => item.id),\n )\n : legacyFavoriteConfiguration(state.data, discovered);\n const configuration = saved || legacy;\n state.items = mergeConfiguredItems(configuration, discovered);\n state.defaultId = configuration.defaultId;\n if (!state.items.some(item => item.id == state.defaultId && item.enabled !== false && item.available)) {\n state.defaultId = state.items.find(item => item.enabled !== false && item.available)?.id || '';\n }\n state.message = '';\n } catch (error) {\n state.message = error.message || String(error);\n }\n renderEditor(state);\n}\n\nfunction initializeEditor(input, mode, widAttr, value) {\n input.value = typeof value == 'string' ? value : '';\n const context = editorContext(input);\n const editor = $(`#inspect_${widAttr}_editor`);\n if (!context || !editor.length) {\n return;\n }\n const state = {\n ...context,\n input,\n editor,\n mode,\n items: [],\n defaultId: '',\n message: '',\n };\n editor.off('.squeezeboxrpcConfig').on('click.squeezeboxrpcConfig', '[data-action]', event => {\n const action = $(event.currentTarget).attr('data-action');\n const index = Number($(event.currentTarget).closest('[data-index]').attr('data-index'));\n if (action == 'refresh') {\n void refreshEditor(state);\n return;\n }\n if (action == 'apply') {\n input.value = serializeItemConfiguration({ version: 1, defaultId: state.defaultId, items: state.items });\n $(input).trigger('change');\n state.message = 'Configuration saved';\n renderEditor(state);\n return;\n }\n if (action == 'up' || action == 'down') {\n state.items = moveConfiguredItem(state.items, index, action == 'up' ? -1 : 1);\n renderEditor(state);\n } else if (action == 'image-select') {\n selectImage(state, index);\n }\n });\n editor.on('change.squeezeboxrpcConfig input.squeezeboxrpcConfig', '[data-index] [data-action]', event => {\n const $target = $(event.currentTarget);\n const action = $target.attr('data-action');\n const index = Number($target.closest('[data-index]').attr('data-index'));\n const item = state.items[index];\n if (!item) {\n return;\n }\n if (action == 'enabled') {\n item.enabled = $target.prop('checked');\n if (!item.enabled && state.defaultId == item.id) {\n state.defaultId = state.items.find(entry => entry.enabled !== false && entry.available)?.id || '';\n renderEditor(state);\n }\n } else if (action == 'default') {\n state.defaultId = item.id;\n } else if (action == 'text' || action == 'image') {\n item[action] = String($target.val() || '');\n }\n });\n void refreshEditor(state);\n}\n\n/**\n * Create a VIS-1 custom editor for stable item selection and ordering.\n *\n * @param mode editor mode\n * @param widAttr widget attribute name\n */\nexport function configurationEditor(mode, widAttr) {\n return {\n input: `<input type=\"hidden\" id=\"inspect_${widAttr}\"><div id=\"inspect_${widAttr}_editor\"></div>`,\n init: function (attribute, value) {\n initializeEditor(this, mode, attribute, value);\n },\n };\n}\n", "'use strict';\n\n/**\n * Normalize an ioBroker adapter-instance object or ID.\n *\n * @param value adapter instance object or ID\n * @returns normalized SqueezeboxRPC instance ID\n */\nexport function normalizeSqueezeboxInstance(value) {\n const id = String(value?._id || value?.id || value || '').replace(/^system\\.adapter\\./, '');\n return /^squeezeboxrpc\\.\\d+$/.test(id) ? id : '';\n}\n\n/**\n * Collect unique SqueezeboxRPC instance IDs from VIS objects or an object-view response.\n *\n * @param source VIS objects, object-view result, or instance list\n * @returns sorted unique instance IDs\n */\nexport function collectSqueezeboxInstances(source) {\n const values = Array.isArray(source)\n ? source\n : Array.isArray(source?.rows)\n ? source.rows.map(row => row.value?._id || row.id)\n : Object.entries(source || {}).map(([id, value]) => value?._id || id);\n return [...new Set(values.map(normalizeSqueezeboxInstance).filter(Boolean))].sort((left, right) =>\n left.localeCompare(right, undefined, { numeric: true }),\n );\n}\n", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\".3\"><path d=\"M14 10H3v2h11zm0-4H3v2h11zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2zM3 16h7v-2H3z\"/></g></svg>\n", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM8 9h8v10H8V9zm7.5-5-1-1h-5l-1 1H5v2h14V4z\"/></svg>\n", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\">\n <g transform=\"matrix(.56122 0 0 .56122 28.082 28.081)\">\n <path d=\"m98 24h15v80h-15z\"/>\n <path transform=\"matrix(1.0892 0 0 1.1187 -4.5514 -7.5937)\" d=\"m58.834 29.054 46.333 29.892a6.0144 6.0144 90 0 1 0 10.108l-46.333 29.892a5.0797 5.0797 28.586 0 1-7.8335-4.2684v-61.355a5.0797 5.0797 151.41 0 1 7.8335-4.2684z\"/>\n <path transform=\"matrix(1.0892 0 0 1.1187 -40.551 -7.5937)\" d=\"m58.834 29.054 46.333 29.892a6.0144 6.0144 90 0 1 0 10.108l-46.333 29.892a5.0797 5.0797 28.586 0 1-7.8335-4.2684v-61.355a5.0797 5.0797 151.41 0 1 7.8335-4.2684z\"/>\n </g>\n</svg>", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\".3\"><path d=\"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z\"/></g></svg>\n", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\".3\"><path d=\"m12 4-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z\"/></g></svg>\n", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <g transform=\"matrix(2.8247 0 0 2.8247 26.631 26.631)\">\n <rect x=\"5.396\" y=\"5.396\" width=\"6.4058\" height=\"15.666\" ry=\".28773\"/>\n <rect x=\"14.656\" y=\"5.396\" width=\"6.4058\" height=\"15.666\" ry=\".28773\"/>\n </g>\n</svg>", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <path d=\"m44.069 33.703 44.77 25.915a5.8115 5.2143 0 0 1 0 8.7633l-44.77 25.915a4.9083 4.4039 0 0 1-7.5692-3.7006v-53.192a4.9083 4.4039 0 0 1 7.5692-3.7006z\"/>\n</svg>\n", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\">\n <g transform=\"matrix(3.5107 0 0 3.5106 17.557 20.769)\" fill=\"currentColor\">\n <path transform=\"scale(.26458)\" d=\"m35.473 20.621c-8.2281 0-14.852 6.6235-14.852 14.852v29.055c0 8.2281 6.6235 14.852 14.852 14.852h29.055c8.2281 0 14.852-6.6235 14.852-14.852v-29.055c0-8.2281-6.6235-14.852-14.852-14.852h-4.0195v9.6641c0 .05754-.01898.1113-.02344.16797 5.108.40503 9.1016 4.6456 9.1016 9.8613v19.371c0 5.4854-4.415 9.9004-9.9004 9.9004h-19.371c-5.4854 0-9.9004-4.415-9.9004-9.9004v-19.371c0-5.4854 4.415-9.9004 9.9004-9.9004h.21094c-.0026-.04363-.01758-.08477-.01758-.12891v-9.6641z\"/>\n <path d=\"m10.111 9.4128v-5.3598c-.0082.018122-.0021-.17387.24672-.34879.24874-.17491.65793 0 .65793 0l4.6078 2.7541s.1702.098349.16971.29612c-.000497.20056-.1784.32361-.1784.32361l-4.5991 2.7487s-.39816.13052-.65793-.063572c-.25976-.19409-.24672-.35035-.24672-.35035z\"/>\n </g>\n</svg>", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\">\n <g transform=\"matrix(1.0443 0 0 1.0443 -1.6877 -1.4835)\" fill=\"currentColor\">\n <path d=\"m49.974 39.646c-7.3148 0-13.204 5.8883-13.204 13.204v25.83c0 7.3148 5.8883 13.204 13.204 13.204h13.599c-.08826-.20751-.18232-.41241-.25351-.63029-.91692-2.8066-.32741-5.663 1.2259-8.0757h-10.267c-4.8766 0-8.8015-3.925-8.8015-8.8015v-17.221c0-4.8765 3.925-8.8015 8.8015-8.8015h.18753c-.0023-.03878-.01563-.07535-.01563-.1146v-8.5915zm22.256 0v8.5915c0 .05114-.0168.09896-.02084.14933 1.4494.11493 2.7963.58042 3.9606 1.3075v-4.2159h9.043l-.158 2.6705v.0069c.0015.72589.46222 1.7794 1.5106 3.1897.6702.90145 1.5365 1.9099 2.4413 3.0177v-1.5141c0-7.3148-5.8883-13.204-13.204-13.204zm12.825 25.264-.0069 20.56c.01981 1.0467-.14027 2.0683-.44277 3.0473 2.6983-2.4141 4.4017-5.9157 4.4017-9.8378v-3.6897c-.50056.10026-1.0682.08993-1.6687-.16321-1.3963-.58871-1.712-1.7874-1.7971-2.4604-.08511-.67302.0027-1.1974.16321-1.7259.07429-.24506.28242-3.0184-.34032-5.0927-.07819-.26036-.22043-.40039-.30907-.63724z\"/>\n <path d=\"m52.414 52.942v-18.009c-.02755.06088-.0071-.58422.829-1.172.83578-.58771 2.2107 0 2.2107 0l15.483 9.254s.57188.33046.57024.99498c-.0017.6739-.59944 1.0874-.59944 1.0874l-15.453 9.2358s-1.3378.43856-2.2107-.2136c-.87281-.65216-.829-1.1772-.829-1.1772z\"/>\n <path d=\"m82.375 48.148h-3.5496v32.228c-1.9626-.84136-4.5025-.85305-7.0078.16182-4.4884 1.82-7.1623 6.247-5.9735 9.8867 1.1895 3.6406 5.7921 5.1154 10.28 3.2955 3.812-1.5454 6.3058-4.9716 6.2447-8.1982l.006-26.357c6.1892 1.0868 6.613 9.805 5.8717 12.25-.28151.92651.2142 1.6203 1.1497 0 6.6738-11.567-7.0212-16.671-7.0212-23.266z\"/>\n </g>\n</svg>", "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M17.65 6.35A7.96 7.96 0 0 0 12 4a8 8 0 1 0 7.73 10h-2.08A6 6 0 1 1 16.22 7.78L13 11h7V4z\"/></svg>\n", "<svg viewBox=\"0 0 128 128\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\">\n <g transform=\"matrix(.56121 0 0 .56122 28.082 28.082)\">\n <path d=\"m30 24h-15v80h15z\"/>\n <path d=\"m68.467 24.908-50.468 33.439a6.5512 6.728 0 0 0 0 11.307l50.468 33.439a5.533 5.6824 0 0 0 8.5326-4.7749v-68.635a5.533 5.6824 0 0 0-8.5326-4.7749z\"/>\n <path d=\"m104.47 24.907-50.468 33.439a6.5512 6.728 0 0 0 0 11.307l50.468 33.439a5.533 5.6824 0 0 0 8.5326-4.7749v-68.635a5.533 5.6824 0 0 0-8.5326-4.7749z\"/>\n </g>\n</svg>", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <g transform=\"translate(-1 -1.5)\">\n <rect x=\"35\" y=\"35\" width=\"40\" height=\"10\"/>\n <rect x=\"55\" y=\"52\" width=\"40\" height=\"10\"/>\n <rect x=\"35\" y=\"69\" width=\"40\" height=\"10\"/>\n <rect x=\"55\" y=\"86\" width=\"40\" height=\"10\"/>\n </g>\n</svg>", "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <path d=\"m34 33.5v10h40v-10h-40zm20 17v10h40v-10h-40zm-20 17v10h34.5v-3.543c0-2.1921 1.7649-3.957 3.957-3.957h1.543v-2.5h-40zm20 17v10h18.457c-2.1921 0-3.957-1.7649-3.957-3.957v-6.043h-14.5z\"/>\n\n <rect\n x=\"72.5\"\n y=\"73\"\n width=\"20\"\n height=\"20\"\n rx=\"3\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n />\n</svg>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n>\n <path\n d=\"M0 0 C15.18 0 30.36 0 46 0 C46 15.18 46 30.36 46 46 C30.82 46 15.64 46 0 46 C0 30.82 0 15.64 0 0 Z\"\n transform=\"translate(41,41)\"\n />\n</svg>", "import add from '../img/add.svg';\nimport deleteIcon from '../img/delete.svg';\nimport fwd from '../img/fwd.svg';\nimport menuback from '../img/menuback.svg';\nimport next from '../img/next.svg';\nimport pause from '../img/pause.svg';\nimport play from '../img/play.svg';\nimport repeat0 from '../img/repeat0.svg';\nimport repeat1 from '../img/repeat1.svg';\nimport refresh from '../img/refresh.svg';\nimport rew from '../img/rew.svg';\nimport shuffle0 from '../img/shuffle0.svg';\nimport shuffle2 from '../img/shuffle2.svg';\nimport stop from '../img/stop.svg';\n\nconst inlineSvg = source => source.replace(/^\\s*<\\?xml[^>]*>\\s*/i, '').trim();\n\nexport const svgIcons = {\n add: inlineSvg(add),\n delete: inlineSvg(deleteIcon),\n fwd: inlineSvg(fwd),\n menuback: inlineSvg(menuback),\n next: inlineSvg(next),\n pause: inlineSvg(pause),\n play: inlineSvg(play),\n repeat0: inlineSvg(repeat0),\n repeat1: inlineSvg(repeat1),\n refresh: inlineSvg(refresh),\n rew: inlineSvg(rew),\n shuffle0: inlineSvg(shuffle0),\n shuffle2: inlineSvg(shuffle2),\n stop: inlineSvg(stop),\n};\n", "/*\n ioBroker.vis squeezeboxrpc Widget-Set\n\n Copyright 2025 oweitman oweitman@gmx.de\n\n*/\n/* globals $,vis,systemDictionary */\n'use strict';\n\n// add translations for edit mode\nimport { version as pkgVersion } from '../../../package.json';\nimport { browser } from './widgets/browser.js';\nimport { favorites } from './widgets/favorites.js';\nimport { players } from './widgets/players.js';\nimport { buttonplay } from './widgets/buttonplay.js';\nimport { buttonfwd } from './widgets/buttonfwd.js';\nimport { buttonrew } from './widgets/buttonrew.js';\nimport { buttonrepeat } from './widgets/buttonrepeat.js';\nimport { buttonshuffle } from './widgets/buttonshuffle.js';\nimport { volumebar } from './widgets/volumebar.js';\nimport { syncgroup } from './widgets/syncgroup.js';\nimport { playtime } from './widgets/playtime.js';\nimport { string } from './widgets/string.js';\nimport { playlist } from './widgets/playlist.js';\nimport { playlistdetail } from './widgets/playlistdetail.js';\nimport { number } from './widgets/number.js';\nimport { datetime } from './widgets/datetime.js';\nimport { image } from './widgets/image.js';\nimport { configurationEditor } from './configurationEditor.js';\nimport { parseItemConfiguration } from './itemConfiguration.js';\nimport { collectSqueezeboxInstances } from './instanceSelection.js';\nimport { svgIcons } from './svgIcons.js';\n\nvar translations = require('../myi18n/translations.json');\n$.extend(true, systemDictionary, translations);\n\n/* fetch('widgets/squeezeboxrpc/myi18n/translations.json').then(async res => {\n const i18n = await res.json();\n\n $.extend(true, systemDictionary, i18n);\n}); */\n\nvis.binds['squeezeboxrpc'] = {\n version: pkgVersion,\n debug: false,\n fetchResults: false,\n playerSelections: {},\n showVersion: function () {\n if (vis.binds['squeezeboxrpc'].version) {\n console.log(`Version squeezeboxrpc: ${vis.binds['squeezeboxrpc'].version}`);\n vis.binds['squeezeboxrpc'].version = null;\n }\n },\n svg: svgIcons,\n playerattributes: [\n 'Playername',\n 'PlayerID',\n 'Connected',\n 'IP',\n 'Power',\n 'Mode',\n 'Time',\n 'Rate',\n 'SyncSlaves',\n 'SyncMaster',\n 'Volume',\n 'PlaylistRepeat',\n 'PlaylistShuffle',\n 'Remote',\n 'Playlist',\n 'PlaylistCurrentIndex',\n 'state',\n 'Duration',\n 'Bitrate',\n 'Album',\n 'ArtworkUrl',\n 'Genre',\n 'Type',\n 'Title',\n 'Artist',\n 'Albumartist',\n 'Trackartist',\n 'Band',\n 'Url',\n 'RadioName',\n ],\n playerConfigurationEditor: function (widAttr) {\n return configurationEditor('players', widAttr);\n },\n favoriteConfigurationEditor: function (widAttr) {\n return configurationEditor('favorites', widAttr);\n },\n instanceSelect: function (widAttr) {\n const inputID = `inspect_${widAttr}`;\n const optionHtml = instances =>\n ['']\n .concat(instances)\n .map(instance => `<option value=\"${instance}\">${instance}</option>`)\n .join('');\n const knownInstances = collectSqueezeboxInstances(vis.objects || {});\n\n setTimeout(() => {\n if (typeof vis.conn.getObjectView != 'function') {\n return;\n }\n vis.conn.getObjectView(\n 'system',\n 'instance',\n {\n startkey: 'system.adapter.squeezeboxrpc.',\n endkey: 'system.adapter.squeezeboxrpc.\\u9999',\n },\n (error, result) => {\n if (error) {\n console.error('Cannot read SqueezeboxRPC instances:', error);\n return;\n }\n const $select = $(`#${inputID}`);\n if (!$select.length) {\n return;\n }\n const selected = $select.val();\n const instances = collectSqueezeboxInstances(result);\n if (selected && !instances.includes(selected)) {\n instances.unshift(selected);\n }\n $select.html(optionHtml(instances)).val(selected);\n },\n );\n }, 0);\n\n return { input: `<select type=\"text\" id=\"${inputID}\">${optionHtml(knownInstances)}</select>` };\n },\n getPlayerWidgetData: function (playerWidgetID) {\n if (vis.widgets?.[playerWidgetID]?.data) {\n return vis.widgets[playerWidgetID].data;\n }\n for (const view of Object.values(vis.views || {})) {\n if (view.widgets?.[playerWidgetID]?.data) {\n return view.widgets[playerWidgetID].data;\n }\n }\n return null;\n },\n getPlayerWidgetType: function (_view, playerWidgetID) {\n return this.getPlayerWidgetData(playerWidgetID)?.formattype || '';\n },\n checkAttributes: function ($div, widgetPlayer) {\n if (!widgetPlayer) {\n $div.html('Please select a player widget');\n return false;\n }\n const playerData = this.getPlayerWidgetData(widgetPlayer);\n if (!playerData?.ainstance) {\n $div.html('Please select an instance at the playerwidget');\n return false;\n }\n const ainstance = playerData.ainstance.split('.');\n if (!ainstance || ainstance[0] != 'squeezeboxrpc') {\n $div.html('Please select an instance at the playerwidget');\n return false;\n }\n return ainstance;\n },\n setChanged: function (widgetPlayer, fdata) {\n $('body')\n .off(`squeezeboxrpcplayerchange.${fdata.widgetID}`)\n .on(`squeezeboxrpcplayerchange.${fdata.widgetID}`, fdata, function (_event, changedWidget) {\n if (changedWidget != widgetPlayer) {\n return;\n }\n const self = fdata.self;\n self.setState(fdata);\n });\n },\n setPlayersChanged: function (\n $div,\n widgetPlayer,\n fdata,\n onChange_callback,\n boundstates_callback,\n playerChanged_callback,\n ) {\n const bindPlayerStates = () => {\n const boundstates = boundstates_callback(fdata);\n if (boundstates?.length) {\n vis.binds['squeezeboxrpc'].bindStates($div, boundstates, onChange_callback, fdata);\n }\n };\n\n $('body')\n .off(`squeezeboxrpcplayerschanged.${fdata.widgetID}`)\n .on(`squeezeboxrpcplayerschanged.${fdata.widgetID}`, (_event, changedWidget) => {\n if (changedWidget != widgetPlayer) {\n return;\n }\n bindPlayerStates();\n playerChanged_callback?.(fdata);\n });\n\n bindPlayerStates();\n },\n bindStates: function (elem, bound, change_callback, fdata) {\n const $div = $(elem);\n const boundstates = $div.data('bound');\n if (boundstates) {\n for (let i = 0; i < boundstates.length; i++) {\n vis.states.unbind(boundstates[i], change_callback);\n }\n }\n $div.data('bound', null);\n $div.data('bindHandler', null);\n\n vis.conn.gettingStates = 0;\n vis.conn.getStates(\n bound,\n function (error, states) {\n if (error) {\n console.error('Cannot read initial widget states:', error);\n }\n vis.updateStates(states || {});\n vis.conn.subscribe(bound);\n for (let i = 0; i < bound.length; i++) {\n bound[i] = `${bound[i]}.val`;\n vis.states.bind(bound[i], change_callback);\n }\n $div.data('bound', bound);\n $div.data('bindHandler', change_callback);\n change_callback.call(fdata);\n }.bind({ fdata, change_callback }),\n );\n },\n attrSelect: function (wid_attr, options) {\n if (wid_attr === 'widgetPlayer') {\n options = this.findPlayerWidgets();\n }\n if (wid_attr === 'widgetFavorites') {\n options = this.findFavoritesWidgets();\n }\n let html = '';\n for (let i = 0; i < options.length; i++) {\n const value = typeof options[i] == 'string' ? options[i] : options[i].value;\n const label = typeof options[i] == 'string' ? options[i] : options[i].label;\n html += `<option value=\"${value}\">${label}</option>`;\n }\n const line = {\n input: `<select type=\"text\" id=\"inspect_${wid_attr}\">${html}</select>`,\n };\n return line;\n },\n playerAttrSelect: function (wid_attr) {\n let html = '';\n const playerattributes = vis.binds['squeezeboxrpc'].playerattributes.sort();\n for (let i = 0; i < playerattributes.length; i++) {\n html += `<option value=\"${playerattributes[i]}\">${playerattributes[i]}</option>`;\n }\n const line = {\n input: `<select type=\"text\" id=\"inspect_${wid_attr}\">${html}</select>`,\n };\n return line;\n },\n findPlayerWidgets: function () {\n const result = [];\n for (const [viewName, view] of Object.entries(vis.views || {})) {\n for (const [widgetID, widget] of Object.entries(view.widgets || {})) {\n if (widget.tpl == 'tplSqueezeboxrpcPlayer') {\n const instance = String(widget.data?.ainstance || '').replace(/^system\\.adapter\\./, '');\n const name = String(widget.data?.name || widgetID);\n result.push({\n value: widgetID,\n label: instance ? `${instance} (${viewName}: ${name})` : `${viewName}: ${name}`,\n });\n }\n }\n }\n return result.sort((left, right) => left.label.localeCompare(right.label, undefined, { numeric: true }));\n },\n findFavoritesWidgets: function () {\n const widgets = vis.views[vis.activeView].widgets;\n const keys = Object.keys(widgets);\n const result = [];\n for (let i = 0; i < keys.length; i++) {\n if (widgets[keys[i]].tpl == 'tplSqueezeboxrpcFavorites') {\n result.push(keys[i]);\n }\n }\n return result;\n },\n getPlayerValues: function (widgetPlayer) {\n const domValues = $(`input[name=${widgetPlayer}], #${widgetPlayer} option`)\n .toArray()\n .reduce(function (acc, cur) {\n if ($(cur).val()) {\n acc.push($(cur).val());\n }\n return acc;\n }, []);\n if (domValues.length) {\n return domValues;\n }\n const published = this.playerSelections[widgetPlayer]?.players;\n if (published?.length) {\n return published.slice();\n }\n const configuration = parseItemConfiguration(this.getPlayerWidgetData(widgetPlayer)?.playerConfiguration);\n return configuration ? configuration.items.filter(item => item.enabled !== false).map(item => item.id) : [];\n },\n getPlayerName: function (widgetPlayer) {\n const domValue = $(`input[name=${widgetPlayer}]:checked, #${widgetPlayer} option:checked`).val();\n if (domValue) {\n return domValue;\n }\n const published = this.playerSelections[widgetPlayer]?.player;\n if (published) {\n return published;\n }\n const configuration = parseItemConfiguration(this.getPlayerWidgetData(widgetPlayer)?.playerConfiguration);\n const players = configuration?.items.filter(item => item.enabled !== false) || [];\n return players.some(item => item.id == configuration?.defaultId) ? configuration.defaultId : players[0]?.id;\n },\n publishPlayerSelection: function (widgetPlayer) {\n const playerData = this.getPlayerWidgetData(widgetPlayer);\n const player = $(`input[name=${widgetPlayer}]:checked, #${widgetPlayer} option:checked`).val();\n const players = $(`input[name=${widgetPlayer}], #${widgetPlayer} option`)\n .toArray()\n .map(element => $(element).val())\n .filter(Boolean);\n if (!playerData?.ainstance || !player) {\n return;\n }\n this.playerSelections[widgetPlayer] = {\n instance: String(playerData.ainstance).replace(/^system\\.adapter\\./, ''),\n player,\n players,\n };\n $('body').trigger('squeezeboxrpcplayerchange', [widgetPlayer]);\n },\n getPlayerNameAsync: async function (widgetPlayer) {\n return new Promise((resolve, reject) => {\n (async () => {\n let i = 0;\n while (i < 1000) {\n let playername = this.getPlayerName(widgetPlayer);\n if (!playername) {\n await new Promise(r => setTimeout(r, 100));\n } else {\n resolve(playername);\n return;\n }\n i++;\n console.log(i);\n }\n reject();\n })();\n });\n },\n onHorizChange: function (widgetID, view, newId) {\n const data = vis.views[view].widgets[widgetID].data;\n if (newId == 'vertical') {\n data.segheight = '100%';\n data.segwidth = '100%';\n } else {\n data.segheight = '20px';\n data.segwidth = '20px';\n }\n return true;\n },\n editDimension: function (widgetID, view, newId, attr) {\n if (newId && typeof newId !== 'object') {\n const e = newId.substring(newId.length - 2);\n if (e !== 'px' && e !== 'em' && newId[newId.length - 1] !== '%') {\n vis.views[view].widgets[widgetID].data[attr] = `${newId}px`;\n }\n }\n },\n browsesendToAsync: async function (instance, command, sendData) {\n let result = await vis.binds['squeezeboxrpc'].sendToAsync(instance, command, sendData);\n if (vis.binds['squeezeboxrpc'].fetchResults) {\n console.debug('debugbrowsersendtoasync', {\n debug: 'debug data',\n instance: instance,\n command: command,\n sendData: sendData,\n result: result,\n });\n }\n return result;\n },\n sendToAsync: async function (instance, command, sendData) {\n console.log(`sendToAsync ${command} ${JSON.stringify(sendData)}`);\n return new Promise((resolve /* , reject */) => {\n // eslint-disable-next-line no-useless-catch\n try {\n vis.conn.sendTo(instance, command, sendData, function (receiveData) {\n resolve(receiveData);\n });\n } catch (error) {\n throw error;\n //reject(error);\n }\n });\n },\n getPlaylistData: async function (instance) {\n console.log(`getPlaylistData`);\n const data = {\n playerid: '',\n cmdArray: ['playlists', '0', '999', 'tags:us'],\n };\n return await this.sendToAsync(instance, 'cmdGeneral', data);\n },\n getPlayerID: async function (state) {\n console.log(`getPlayerID`);\n return new Promise((resolve, reject) => {\n try {\n vis.conn.gettingStates = 0;\n vis.conn.getStates([state], function (error, states) {\n resolve(states[state].val);\n });\n } catch (error) {\n reject(error);\n }\n });\n },\n browser,\n favorites,\n players,\n buttonplay,\n buttonfwd,\n buttonrew,\n buttonrepeat,\n buttonshuffle,\n volumebar,\n syncgroup,\n playtime,\n string,\n playlist,\n playlistdetail,\n number,\n datetime,\n image,\n};\nvis.binds['squeezeboxrpc'].showVersion();\n//function css() {} // remove tagged temlate string error message, tagging is needed to format the css code\n// function html() {} // remove tagged temlate string error message, tagging is needed to format the html code\n", "import './sbClasses.js';\nimport './squeezeboxrpc.js';\nimport './date.format.js';\nimport './textImage.js';\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["p", "i", "favorites", "favorites", "fdata", "data", "players", "image", "image", "image", "players", "image", "players", "image", "players", "fdata", "data", "players", "playername", "stateid1", "stateid2", "state1", "state2", "state", "players", "players", "playlist", "fdata", "number", "players", "number", "players", "players", "instance", "players"]
|
|
7
7
|
}
|