UNPKG

iobroker.squeezeboxrpc

Version:

ioBroker Logitech Squeezebox Adapter over JSON/RPC-Protocol

1,410 lines (1,406 loc) 187 kB
"use strict"; (() => { var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // squeezeboxrpc/js/sbClasses.js function parseRequestFactory(request) { console.log(`parseRequestFactory`); let result = request.result; if (result.albums_loop) { return new Albums(request); } if (result.artists_loop) { return new Artists(request); } if (result.genres_loop) { return new Genres(request); } if (result.works_loop) { return new Works(request); } if (result.years_loop) { return new Years(request); } if (result.item_loop) { return new Items(request); } if (result.titles_loop) { return new Tracks(request); } if (result.playlisttracks_loop) { return new PlaylistTracks(request); } if (result.playlists_loop) { return new Playlists(request); } let requestCommand = request.params[1][0]; if (requestCommand === "selectVirtualLibrary" && !result.item_loop) { return new Items(request); } } function object2Array(obj) { return Object.keys(obj).map(function(key) { return `${key}:${obj[key]}`; }); } function getParamsFromCommand(params, key) { return params.find((item) => item.toString().startsWith(key)); } function translateMyMusicParameters(command) { console.log(command); if (command.cmd == void 0) { return void 0; } var cmd = { command: [...command.cmd], params: [] }; for (var key in command.params) { let p2 = command.params[key]; if (p2 != void 0 && p2 != null && p2.length > 0) { cmd.params.push(`${key}:${p2}`); } } let c = []; let p = []; var mode = void 0; var canReplace = true; var hasSort = false; var hasTags = false; var hasArtistId = false; var hasLibraryId = false; var hasNonArtistRole = false; for (let i2 = 0, params = cmd.params; i2 < cmd.params.length; i2++) { if (params[i2].startsWith("mode:")) { mode = params[i2].split(":")[1]; if (mode.startsWith("myMusicArtists")) { mode = "artists"; } else if (mode.startsWith("myMusicAlbums") || mode == "randomalbums" || mode == "vaalbums" || mode == "recentlychanged") { mode = "albums"; } else if (mode == "years") { p.push("hasAlbums:1"); } else if (mode.startsWith("myMusicWorks")) { mode = "works"; } else if (mode != "artists" && mode != "albums" && mode != "genres" && mode != "tracks" && mode != "playlists" && mode != "works") { canReplace = false; break; } c.push(mode); } if (!params[i2].startsWith("menu:")) { if (params[i2].startsWith("tags:")) { if (params[i2].split(":")[1].indexOf("s") < 0) { i2 += "s"; } p.push(params[i2]); hasTags = true; } else { p.push(params[i2]); if (params[i2].startsWith("sort:")) { hasSort = true; } else if (params[i2].startsWith("artist_id:")) { hasArtistId = true; } else if (params[i2].startsWith("library_id:")) { hasLibraryId = true; } else if (params[i2].startsWith("role_id:")) { var role = params[i2].split(":")[1].toLowerCase(); if ("albumartist" != role && "5" != role) { hasNonArtistRole = true; } } } } } if (canReplace && c.length == 1 && mode) { if (mode == "tracks") { if (!hasTags) { p.push("tags:distbhz1kyuAACGPSc"); } if (!hasSort) { p.push("sort:tracknum"); } } else if (mode == "albums") { if (!hasTags) { p.push(hasArtistId ? "ArAlTP" : "AlTP"); } if (!hasSort) { p.push(`sort:album`); } } else if (mode == "playlists") { if (!hasTags) { p.push("PlTP"); } } else if (!hasTags) { if (mode == "artists" || mode == "vaalbums") { p.push("ArTP"); if (!hasLibraryId && !hasNonArtistRole) { p.push("include_online_only_artists:1"); } } else if (mode == "years" || mode == "genres") { p.push("tags:s"); } } cmd = { command: c, params: p }; } if (cmd.params.length > 0) { for (var i = 0, len = cmd.params.length; i < len; ++i) { cmd.params[i] = cmd.params[i].replace("ArAlTP", "tags:aajlqswyKRSSW2").replace("ArTP", "tags:s").replace("PlTP", "tags:suxE").replace("AlTP", "tags:ajlqswyKS2"); } } cmd.params.push("menu:1"); cmd.params.push("library_id:-1"); return __spreadValues({}, cmd); } var Albums, Album, Artists, Artist, Genres, Genre, Playlists, Playlist, Works, Work, Years, Year, Tracks, Track, PlaylistTracks, PlaylistTrack, Items, Item, ItemApplication, ItemRadio, ItemMenu, ItemFilesystem, ItemPlaylist, ItemText, ItemAudio, ItemVirtualLibrary, ItemVirtualLibraryAnswer; var init_sbClasses = __esm({ "squeezeboxrpc/js/sbClasses.js"() { "use strict"; Albums = class { constructor(request) { console.log(`Albums`); this.albums = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.albums_loop) { let albums = result.albums_loop; return albums.map((item) => { return new Album(item, request); }); } } getMenuItems() { return this.albums.map((item) => item.getMenu()); } }; Album = class { constructor(request_item, request) { this.parseRequest(request_item, request); } parseRequest(request_item, request) { this.id = request_item.id || void 0; this.performance = request_item.performance || void 0; this.favorites_url = request_item.favorites_url || void 0; this.favorites_title = request_item.favorites_title || void 0; this.album = request_item.album || void 0; this.year = request_item.year || void 0; this.artwork_track_id = request_item.artwork_track_id || void 0; this.compilation = request_item.compilation || void 0; this.artist_id = request_item.artist_id || void 0; this.artist = request_item.artist || void 0; this.textkey = request_item.textkey || void 0; let additionalPlayParams = [getParamsFromCommand(request.params[1], "role_id:")]; this.actions = { next: { command: ["tracks"], params: ["tags:distbhz1kyuAACGPSE", "sort:tracknum", `album_id:${this.id}`] }, play: { command: ["playlistcontrol"], params: [`cmd:load`, `album_id:${this.id}`, `performance:`, ...additionalPlayParams, `library_id:-1`] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `album_id:${this.id}`, `performance:`] } }; } getMenu() { return { id: this.id, title: `${this.artist} / ${this.album} ${this.year ? `(${this.year})` : ""}`, image: `/music/${this.artwork_track_id}/cover_300x300_f`, type: "album", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; Artists = class { constructor(request) { console.log(`Artists`); this.artists = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.artists_loop) { let artists = result.artists_loop; return artists.map((item) => { return new Artist(item, request); }); } } getMenuItems() { return this.artists.map((item) => item.getMenu()); } }; Artist = class { constructor(request_item, request) { this.parseRequest(request_item, request); } parseRequest(request_item, request) { this.id = request_item.id || void 0; this.artist = request_item.artist || void 0; this.textkey = request_item.textkey || void 0; this.favorites_url = request_item.favorites_url || void 0; let additionalPlayParams = [getParamsFromCommand(request.params[1], "role_id:")]; this.actions = { next: { command: ["albums"], params: ["tags:aajlqswyKSSE", "sort:yearalbum", `artist_id:${this.id}`] }, play: { command: ["playlistcontrol"], params: [ `cmd:load`, `role_id:ALBUMARTIST`, `artist_id:${this.id}`, `sort:yearalbum`, ...additionalPlayParams, `library_id:-1` ] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `role_id:ALBUMARTIST`, `artist_id:${this.id}`, `sort:yearalbum`] } }; } getMenu() { return { id: this.id, title: this.artist, image: `/imageproxy/mai/artist/${this.id}/image_300x300_f`, type: "artist", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; Genres = class { constructor(request) { console.log(`Genres`); this.genres = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.genres_loop) { let genres = result.genres_loop; return genres.map((item) => { return new Genre(item); }); } } getMenuItems() { return this.genres.map((item) => item.getMenu()); } }; Genre = class { constructor(request_item) { this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.id || void 0; this.genre = request_item.genre || void 0; this.textkey = request_item.textkey || void 0; this.favorites_url = request_item.favorites_url || void 0; this.actions = { next: { command: ["tracks"], params: [`genre_id:${request_item.id}`, "tags:distbhz1kyuAACGPScelyE", "msk-sort:yearalbumtrack:Album"] }, play: { command: ["playlistcontrol"], params: [`cmd:load`, `genre_id:${this.id}`, `sort:album`, `library_id:-1`] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `genre_id:${this.id}`, `sort:album`] } }; } getMenu() { return { id: this.id, title: `${this.genre}`, image: null, type: "genre", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; Playlists = class { constructor(request) { console.log(`Playlists`); this.playlists = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.playlists_loop) { let playlists = result.playlists_loop; return playlists.map((item) => { return new Playlist(item); }); } } getMenuItems() { return this.playlists.map((item) => item.getMenu()); } }; Playlist = class { constructor(request_item) { this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.id || void 0; this.playlist = request_item.playlist || void 0; this.url = request_item.url || void 0; this.favorites_url = request_item.favorites_url || void 0; this.textkey = request_item.textkey || void 0; this.extid = request_item.extid || void 0; this.remote = request_item.remote || void 0; this.actions = { next: { command: ["playlists", "tracks"], params: [`playlist_id:${request_item.id}`, "tags:distbhz1acelyAGKPS"] }, play: { command: ["playlistcontrol"], params: [`cmd:load`, `playlist_id:${this.id}`, `performance:`] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `playlist_id:${this.id}`, `performance:`] } }; } getMenu() { return { id: this.id, title: `${this.playlist}`, image: null, type: "playlist", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; Works = class { constructor(request) { console.log(`Works`); this.works = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.works_loop) { let works = result.works_loop; return works.map((item) => { return new Work(item); }); } } getMenuItems() { return this.works.map((item) => item.getMenu()); } }; Work = class { constructor(request_item) { this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.work_id || void 0; this.composer = request_item.composer || void 0; this.work = request_item.work || void 0; this.composer_id = request_item.composer_id || void 0; this.album_id = request_item.album_id || void 0; this.textkey = request_item.textkey || void 0; this.favorites_url = request_item.favorites_url || void 0; this.favorites_title = request_item.favorites_title || void 0; this.actions = { next: { command: ["albums"], params: [ "tags:aajlqswyKSSE", `work_id:${this.id}`, `composer_id:${this.composer_id}`, `album_id:${this.album_id}` ] }, play: { command: ["playlistcontrol"], params: [`cmd:load`, `work_id:${this.id}`, `album_id:${this.album_id}`, `performance:`] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `work_id:${this.id}`, `album_id:${this.album_id}`, `performance:`] } }; } getMenu() { return { id: `work_id:${this.id}`, title: `${this.favorites_title}`, image: null, type: "work", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; Years = class { constructor(request) { console.log(`Years`); this.years = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.years_loop) { let years = result.years_loop; return years.map((item) => { return new Year(item); }); } } getMenuItems() { return this.years.map((item) => item.getMenu()); } }; Year = class { constructor(request_item) { this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.year || void 0; this.year = request_item.year || void 0; this.favorites_url = request_item.favorites_url || void 0; this.actions = { next: { command: ["albums"], params: [ "release_type:Album", "tags:aajlqswyKSSE", "sort:album", "menu:1", `year:${request_item.year}` ] }, play: { command: ["playlistcontrol"], params: [`cmd:load`, `year:${this.id}`, `library_id:-1`] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `year:${this.id}`] } }; } getMenu() { return { id: `year_id:${this.id}`, title: `${this.year}`, image: null, type: "year", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; Tracks = class { constructor(request) { console.log(`Tracks`); this.tracks = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.titles_loop) { let tracks = result.titles_loop; return tracks.map((item) => { return new Track(item); }); } } getMenuItems() { return this.tracks.map((item) => item.getMenu()); } }; Track = class { constructor(request_item) { this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.id || void 0; this.title = request_item.title || void 0; this.duration = request_item.duration || void 0; this.artist_id = request_item.artist_id || void 0; this.tracknum = request_item.tracknum || void 0; this.year = request_item.year || void 0; this.albumartist = request_item.albumartist || void 0; this.trackartist = request_item.trackartist || void 0; this.compilation = request_item.compilation || void 0; this.genres = request_item.genres || void 0; this.genre_ids = request_item.genre_ids || void 0; this.albumartist_ids = request_item.albumartist_ids || void 0; this.trackartist_ids = request_item.trackartist_ids || void 0; this.actions = { play: { command: ["playlistcontrol"], params: [`cmd:load`, `track_id:${this.id}`] }, add: { command: ["playlistcontrol"], params: [`cmd:add`, `track_id:${this.id}`] } }; } getMenu() { return { id: `track_id:${this.id}`, title: `${this.title}`, image: null, type: "track", item: this, actions: JSON.stringify(this.actions) }; } }; PlaylistTracks = class { constructor(request) { console.log(`PlaylistTracks`); this.playlisttracks = this.parseRequest(request); } parseRequest(request) { let result = request.result; if (result.playlisttracks_loop) { let playlisttracks = result.playlisttracks_loop; return playlisttracks.map((item) => { return new PlaylistTrack(item); }); } } getMenuItems() { return this.playlisttracks.map((item) => item.getMenu()); } }; PlaylistTrack = class { constructor(request_item) { this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.id || void 0; this.title = request_item.title || void 0; this["playlist index"] = request_item["playlist index"] || void 0; this.title = request_item.title || void 0; this.duration = request_item.duration || void 0; this.artist_ids = request_item.artist_ids || void 0; this.tracknum = request_item.tracknum || void 0; this.artist = request_item.artist || void 0; this.coverid = request_item.coverid || void 0; this.album_id = request_item.album_id || void 0; this.album = request_item.album || void 0; this.year = request_item.year || void 0; this.genres = request_item.genres || void 0; this.genre_ids = request_item.genre_ids || void 0; this.artist_ids = request_item.artist_ids || void 0; this.actions = { next: { command: ["playlist", "tracks"], params: ["tags:distbhz1acelyAGKPS", "playlist_id:${this.id}"] }, play: { command: ["playlistcontrol"], params: [`menu:1`, `cmd:load`, `folder_id:${this.id}`] }, add: { command: ["playlistcontrol"], params: [`menu:1`, `cmd:add`, `folder_id:${this.id}`] } }; } getMenu() { return { id: `track_id:${this.id}`, title: `${this.title}`, image: null, type: "playlisttrack", item: this }; } }; Items = class { constructor(request) { console.log(`Items`); let filesystem = request.params[1].includes("mode:filesystem"); let requestCommand = request.params[1][0] + (filesystem ? "FS" : ""); this.items = this.parseRequest(request, requestCommand); } parseRequest(request, requestCommand) { let result = request.result; if (result.item_loop) { let items = result.item_loop; return items.map((item) => { return Item.create(item, requestCommand, request); }); } if (!result.titles_loop && requestCommand === "selectVirtualLibrary") { return [ Item.create( { type: "virtualLibraryAnswer", text: request.result.title }, requestCommand ) ]; } } getMenuItems() { return this.items.map((item) => item.getMenu()); } }; Item = class { // item types // search|text|textarea|audio|playlist|link|opml|replace|redirect|radio static create(request_item, requestCommand, request) { console.log(`Item switch: ${requestCommand}_${request_item.type || ""}`); switch (`${requestCommand}_${request_item.type || ""}`) { case "radios_": case "local_": case "music_": case "sports_": case "news_": case "talk_": case "location_": case "language_": case "podcast_": case "local_link": case "music_link": case "sports_link": case "news_link": case "talk_link": case "location_link": case "language_link": case "podcast_link": return new ItemRadio(request_item, requestCommand); case "local_text": case "music_text": case "sports_text": case "news_text": case "talk_text": case "location_text": case "language_text": case "podcast_text": case "browselibrary_text": case "browselibraryFS_text": return new ItemText(request_item, requestCommand); case "menu_": return new ItemMenu(request_item, request); case "browselibrary_playlist": case "favorites_playlist": return new ItemPlaylist(request_item, false); case "browselibraryFS_playlist": return new ItemPlaylist(request_item, true); case "browselibraryFS_": return new ItemFilesystem(request_item); case "browselibrary_audio": //ok case "browselibraryFS_audio": //ok case "local_audio": //ok case "music_audio": //ok case "sports_audio": //ok case "news_audio": //ok case "talk_audio": //ok case "location_audio": //ok case "language_audio": //ok case "podcast_audio": //ok case "favorites_audio": return new ItemAudio(request_item, requestCommand); case "selectVirtualLibrary_virtualLibraryAnswer": return new ItemVirtualLibraryAnswer(request_item); case "selectVirtualLibrary_": case "selectVirtualLibrary_outline": return new ItemVirtualLibrary(request_item); case "myapps_redirect": return new ItemApplication(request_item); default: return new ItemMenu(request_item, request); } } }; ItemApplication = class extends Item { constructor(request_item) { super(request_item); this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.actions.go.params.menu || void 0; this.text = request_item.text.trim() || void 0; this.iconid = request_item["icon-id"] || void 0; this.actions = {}; if (request_item.actions["go"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { next: translateMyMusicParameters(request_item.actions.go) }); } if (request_item.actions["play"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { play: translateMyMusicParameters(request_item.actions.play) }); } if (request_item.actions["add"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { add: translateMyMusicParameters(request_item.actions.add) }); } } getMenu() { return { id: this.id, title: this.text, image: this.icon, type: "itemapplication", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; ItemRadio = class extends Item { constructor(request_item, requestCommand) { super(request_item); this.parseRequest(request_item, requestCommand); } parseRequest(request_item, requestCommand) { var _a, _b; let cmd; if ((_a = request_item.actions) == null ? void 0 : _a.go) { cmd = translateMyMusicParameters((_b = request_item.actions) == null ? void 0 : _b.go); } else { cmd = { command: [requestCommand, "items"], params: [`menu:${requestCommand}`, `item_id:${request_item.actions.go.params.item_id}`] }; } this.id = request_item.actions.go.params.item_id || request_item.actions.go.params.menu || void 0; this.text = request_item.text || void 0; this.actions = { next: cmd }; } getMenu() { return { id: `item_id:${this.id}`, title: this.text, image: null, type: "radiolocal", param: JSON.stringify(this.actions.next), item: this, actions: JSON.stringify(this.actions) }; } }; ItemMenu = class extends Item { constructor(request_item, request) { super(request_item); this.parseRequest(request_item, request); } parseRequest(request_item, request) { this.id = request_item.text || void 0; this.text = request_item.text || "Empty"; this.node = request_item.node || void 0; this.weight = request_item.weight || void 0; if (request_item.actions) { if (request_item.actions["go"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { next: translateMyMusicParameters(request_item.actions.go) }); } if (request_item.actions["play"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { play: translateMyMusicParameters(request_item.actions.play) }); } if (request_item.actions["add"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { add: translateMyMusicParameters(request_item.actions.add) }); } if (request_item.actions["do"]) { this.actions = __spreadValues(__spreadValues({}, this.actions), { add: translateMyMusicParameters(request_item.actions.do) }); } } if (request_item.goAction) { if (request_item.goAction == "play") { const filteredParams = Object.keys(request_item.params).filter((key) => !key.includes("touchToPlay")).reduce((obj, key) => { obj[key] = request_item.params[key]; return obj; }, {}); this.actions = { play: { command: request.result.base.actions[request_item.goAction].cmd, params: [ ...object2Array(__spreadValues(__spreadValues({}, request.result.base.actions[request_item.goAction].params), filteredParams)) ] } }; } } } getMenu() { return { id: this.id, title: this.text, image: null, type: "menu", actions: JSON.stringify(this.actions), item: this }; } }; ItemFilesystem = class extends Item { constructor(request_item) { super(request_item); this.parseRequest(request_item); } parseRequest(request_item) { var _a, _b, _c; let cmd; if ((_a = request_item.actions) == null ? void 0 : _a.go) { cmd = translateMyMusicParameters((_b = request_item.actions) == null ? void 0 : _b.go); } this.id = ((_c = request_item.actions) == null ? void 0 : _c.go.params.item_id) || void 0; this.text = request_item.text || void 0; this.actions = { next: cmd }; } getMenu() { return { id: this.id, title: this.text, image: null, type: "menu", param: JSON.stringify(this.actions.next), item: this, actions: JSON.stringify(this.actions) }; } }; ItemPlaylist = class extends Item { constructor(request_item, filesystem) { super(request_item); this.parseRequest(request_item, filesystem); } parseRequest(request_item, filesystem) { var _a; this.id = ((_a = request_item.actions) == null ? void 0 : _a.more.params.folder_id) || void 0; this.text = request_item.text || void 0; this.textkey = request_item.textkey || void 0; this.actions = { next: { command: ["browselibrary", "items"], params: [ "menu:browselibrary", filesystem ? "mode:filesystem" : "mode:bmf", ...object2Array(request_item.params) ] }, play: { command: ["playlistcontrol"], params: [`menu:1`, `cmd:load`, `folder_id:${this.id}`] }, add: { command: ["playlistcontrol"], params: [`menu:1`, `cmd:add`, `folder_id:${this.id}`] } }; } getMenu() { return { id: `item_id:${this.id}`, title: `(D) ${this.text}`, image: null, type: "itemplaylist", param: JSON.stringify(this.actions.next), item: this, actions: JSON.stringify(this.actions) }; } }; ItemText = class extends Item { constructor(request_item) { super(request_item); this.parseRequest(request_item); } parseRequest(request_item) { this.id = request_item.text || void 0; this.text = request_item.text || void 0; } getMenu() { return { id: `item_id:${this.id}`, title: this.text, image: null, type: "itemtext", param: null, item: this }; } }; ItemAudio = class extends Item { constructor(request_item, requestCommand) { super(request_item); this.parseRequest(request_item, requestCommand); } parseRequest(request_item, requestCommand) { var _a, _b; this.id = ((_a = request_item.commonParams) == null ? void 0 : _a.track_id) || ((_b = request_item.params) == null ? void 0 : _b.item_id) || void 0; this.text = request_item.text || void 0; this.textkey = request_item.textkey || void 0; this.icon = request_item.icon || void 0; this.iconid = request_item["icon-id"] || void 0; this.favorites_type = request_item.presetParams.favorites_type || void 0; this.favorites_url = request_item.presetParams.favorites_url || void 0; this.favorites_title = request_item.presetParams.favorites_title || void 0; this.icon = request_item.presetParams.icon || void 0; this.actions = { play: { command: [...requestCommand === "browselibraryFS" ? ["browselibrary"] : [requestCommand]], params: [ "playlist", "play", ...requestCommand === "browselibrary" ? ["mode:bmf"] : [], ...requestCommand === "browselibraryFS" ? ["mode:filesystem"] : [], ...requestCommand === "browselibraryFS" ? ["menu:browselibrary"] : [requestCommand], `item_id:${this.id}`, `isContextMenu:1` ] }, add: { command: [...requestCommand === "browselibraryFS" ? ["browselibrary"] : [requestCommand]], params: [ "playlist", "add", ...requestCommand === "browselibrary" ? ["mode:bmf"] : [], ...requestCommand === "browselibraryFS" ? ["mode:filesystem"] : [], ...requestCommand === "browselibraryFS" ? ["menu:browselibrary"] : [requestCommand], `item_id:${this.id}`, `isContextMenu:1` ] } }; } getMenu() { return { id: `item_id:${this.id}`, title: `${this.text}`, image: this.icon, type: "itemaudio", item: this, actions: JSON.stringify(this.actions) }; } }; ItemVirtualLibrary = class extends Item { constructor(request_item) { super(request_item); this.parseRequest(request_item); } parseRequest(request_item) { var _a; this.id = ((_a = request_item.actions) == null ? void 0 : _a.go.params.item_id) || void 0; this.text = request_item.text || void 0; let cmd = { command: ["selectVirtualLibrary", "items"], params: [`item_id:${request_item.actions.go.params.item_id}`, "menu:selectVirtualLibrary"] }; this.actions = { next: cmd }; } getMenu() { return { id: `item_id:${this.id}`, title: this.text, image: null, type: "itemvirtuallibrary", item: this, param: JSON.stringify(this.actions.next), actions: JSON.stringify(this.actions) }; } }; ItemVirtualLibraryAnswer = class extends Item { constructor(request_item) { super(request_item); this.parseRequest(request_item); } parseRequest(request_item) { var _a; this.id = ((_a = request_item.actions) == null ? void 0 : _a.go.params.item_id) || void 0; this.text = request_item.text || void 0; } getMenu() { return { id: `item_id:${this.id}`, title: this.text, image: null, type: "itemvirtuallibraryanswer", item: this, param: null }; } }; } }); // ../package.json var version; var init_package = __esm({ "../package.json"() { version = "1.6.0"; } }); // squeezeboxrpc/js/textImage.js function wordwrap(str, width, opt) { opt = opt || {}; const splitChars = [" ", "-", " "]; if (opt.wrapCamelCase) { str = str.replace(/([a-z])([A-Z])/gm, "$1 $2"); } const words = explode(str, splitChars); let curLineLength = 0; let strBuilder = ""; for (let i = 0; i < words.length; i += 1) { let word = words[i]; if (curLineLength + word.length > width) { if (curLineLength > 0) { strBuilder += "\n"; curLineLength = 0; } while (word.Length > width) { strBuilder += `${word.substring(0, width - 1)}-`; word = word.substring(width - 1); strBuilder += "\n"; } word = word.trimStart(); } if (curLineLength == 0 && /^\s+$/.test(word)) { word = word.trimStart(); } strBuilder += word; curLineLength += word.length; } return strBuilder; } function explode(str) { const parts = []; let startIndex = 0; while (true) { const index = str.regexIndexOf(/[ |\t|-]/gm, startIndex); if (index == -1) { parts.push(str.substring(startIndex)); return parts; } const word = str.substring(startIndex, startIndex + index - startIndex); const nextChar = str.substring(index, index + 1)[0]; if (/^\s+$/.test(nextChar)) { parts.push(word); parts.push(nextChar); } else { parts.push(word + nextChar); } startIndex = index + 1; } } function getTextWidth(text, font) { const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); const context = canvas.getContext("2d"); context.font = font.getfont(); const metrics = context.measureText(text); return metrics.width; } function getGoodFontSize(lines, picWidth, font) { while (true) { const maxWidth = getMaxPixelWidth(lines, font); if (maxWidth > picWidth) { font.decFontSize(); } else { return font; } } } function createCanvas(lines, font, picWidth, picHeight, lineHeight, opt) { opt = opt || {}; const canvas = document.createElement("canvas"); $("body").append(canvas); canvas.width = picWidth; canvas.height = picHeight; const ctx = canvas.getContext("2d"); ctx.fillStyle = opt.style ? opt.backgroundcolor : "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.font = font.getfont(); ctx.fillStyle = opt.style ? opt.style.color : "white"; ctx.textAlign = opt.style ? opt.style.textAlign : "center"; let x = 0; if (opt.style) { if (opt.style.direction == "ltr") { if (opt.style.textAlign == "start" || opt.style.textAlign == "left") { x = 0; } if (opt.style.textAlign == "end" || opt.style.textAlign == "right") { x = picWidth; } if (opt.style.textAlign == "center") { x = picWidth / 2; } } if (opt.style.direction == "rtl") { if (opt.style.textAlign == "end" || opt.style.textAlign == "left") { x = 0; } if (opt.style.textAlign == "start" || opt.style.textAlign == "right") { x = picWidth; } if (opt.style.textAlign == "center") { x = picWidth / 2; } } } else { x = picWidth / 2; } const y = font.getDescent() + Math.floor((picHeight - lines.length * lineHeight) / 2); ctx.textBaseline = "top"; for (let i = 0; i < lines.length; i++) { ctx.fillText(lines[i], x, y + i * lineHeight); } return canvas; } function getMaxChars(lines) { return lines.reduce( function(acc, cur) { return Math.max(acc, cur.length); }.bind(this), 0 ); } function getMaxPixelWidth(lines, font) { return lines.reduce( function(acc, cur) { return Math.max(acc, getTextWidth(cur.trim(), font)); }.bind(this), 0 ); } function createTextImage(text, font, picWidth, picHeight, opt) { opt = opt || {}; font = typeof font == "string" ? new Font(font) : font; const lineHeight = font.getHeight(); const charWidth = font.getWidth(); const maxChars = picWidth / charWidth; let maxLines = picHeight / lineHeight - 1; maxLines = maxLines < 0 ? 1 : maxLines; let lines; if (picHeight >= picWidth) { for (let textWidth = 1; (lines = wordwrap(text, textWidth, opt).split("\n")) && maxLines + 1 < lines.length; textWidth++) { } } else { for (let textWidth = 1; (lines = wordwrap(text, textWidth, opt).split("\n")) && getMaxChars(lines) < maxChars && lines.length > 1; textWidth++) { } } const goodFont = getGoodFontSize(lines, picWidth, font); return createCanvas(lines, goodFont, picWidth, picHeight, lineHeight, opt); } var getTextHeight, Font; var init_textImage = __esm({ "squeezeboxrpc/js/textImage.js"() { "use strict"; String.prototype.regexIndexOf = function(regex, startpos) { const indexOf = this.substring(startpos || 0).search(regex); return indexOf >= 0 ? indexOf + (startpos || 0) : indexOf; }; getTextHeight = function(font) { const text = $("<span>Hg</span>").css({ font: font.getfont() }); const block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>'); const div = $("<div></div>"); div.append(text, block); const body = $("body"); body.append(div); const result = {}; try { block.css({ verticalAlign: "baseline" }); result.ascent = block.offset().top - text.offset().top; block.css({ verticalAlign: "bottom" }); result.height = block.offset().top - text.offset().top; result.descent = result.height - result.ascent; } finally { div.remove(); } return result; }; Font = class { /** * Creates a Font object for the given element. * * @param elem the element to get the font string from */ constructor(elem) { this.span = document.createElement("span"); const fontstr = this.getFontString(elem[0]); this.span.style.font = fontstr; this.measure = getTextHeight(this); this.measure.width = getTextWidth("M", this); } getAscent() { return this.measure.ascent; } getDescent() { return this.measure.descent; } getWidth() { return this.measure.width; } getHeight() { return this.measure.height; } /** * Returns the current font string for the font. * * @returns The current font string. */ getfont() { return this.span.style.font; } /** * Set the font string for the font. * * @param fontstr the new font string * @returns The Font object, to allow chaining. */ setfont(fontstr) { this.span.style.font = fontstr; return this; } /** * Increase the font size of the font by one pixel. * * @returns The Font object, to allow chaining. */ incFontSize() { this.span.style.fontSize = `${parseInt(this.span.style.fontSize) + 1}px`; return this; } /** * Decrease the font size of the font by one pixel. * * @returns The Font object, to allow chaining. */ decFontSize() { this.span.style.fontSize = `${parseInt(this.span.style.fontSize) - 1}px`; return this; } /** * Given an element, returns the CSS font string for that element. * * @param elem - The element to get the font string for. * @returns The CSS font string, or 'normal 12px sans-serif' if no font style is set. */ getFontString(elem) { const style = window.getComputedStyle(elem); let elementFont = style.getPropertyValue("font"); if (elementFont) { return elementFont; } const fontStyle = style.getPropertyValue("font-style"); const fontVariant = style.getPropertyValue("font-variant"); const fontWeight = style.getPropertyValue("font-weight"); const fontSize = style.getPropertyValue("font-size"); const fontFamily = style.getPropertyValue("font-family"); elementFont = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize} ${fontFamily}`.replace(/ +/g, " ").trim(); return elementFont ? elementFont : "normal 12px sans-serif"; } }; } }); // squeezeboxrpc/js/squeezeboxrpc.js var require_squeezeboxrpc = __commonJS({ "squeezeboxrpc/js/squeezeboxrpc.js"(exports) { "use strict"; init_package(); init_textImage(); init_sbClasses(); fetch("widgets/squeezeboxrpc/i18n/translations.json").then((res) => __async(exports, null, function* () { const i18n = yield res.json(); $.extend(true, systemDictionary, i18n); })); vis.binds["squeezeboxrpc"] = { version, debug: false, fetchResults: false, showVersion: function() { if (vis.binds["squeezeboxrpc"].version) { console.log(`Version squeezeboxrpc: ${vis.binds["squeezeboxrpc"].version}`); vis.binds["squeezeboxrpc"].version = null; } }, svg: { stop: '<svg version="1.1" viewBox="0 0 26.458 26.458" xmlns="http://www.w3.org/2000/svg"><g fill="#ffffff" stroke="#ffffff" stro