diff --git a/package-lock.json b/package-lock.json index 4efa1c2a..14d7ba3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "lodash": "^4.17.21", "md5": "^2.3.0", "memoize-one": "^6.0.0", + "mpris-service": "^2.1.2", "nanoid": "^3.3.3", "net": "^1.0.2", "node-mpv": "^2.0.0-beta.2", @@ -1932,6 +1933,14 @@ "node": ">= 8" } }, + "node_modules/@nornagon/put": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", + "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==", + "engines": { + "node": ">=0.3.0" + } + }, "node_modules/@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", @@ -3576,6 +3585,23 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/abstract-socket": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", + "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ], + "dependencies": { + "bindings": "^1.2.1", + "nan": "^2.12.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -4577,6 +4603,15 @@ "node": ">=8" } }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -4910,8 +4945,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/builder-util": { "version": "23.6.0", @@ -5123,7 +5157,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -6642,6 +6675,23 @@ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz", "integrity": "sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ==" }, + "node_modules/dbus-next": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", + "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", + "dependencies": { + "@nornagon/put": "0.0.8", + "event-stream": "3.3.4", + "hexy": "^0.2.10", + "jsbi": "^2.0.5", + "long": "^4.0.0", + "safe-buffer": "^5.1.1", + "xml2js": "^0.4.17" + }, + "optionalDependencies": { + "abstract-socket": "^2.0.0" + } + }, "node_modules/de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -6750,6 +6800,22 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -6804,7 +6870,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -7257,8 +7322,7 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, "node_modules/duplexer3": { "version": "0.1.4", @@ -9585,6 +9649,20 @@ "node": ">= 0.6" } }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -10181,6 +10259,12 @@ "node": ">= 12" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -10425,6 +10509,11 @@ "node": ">= 0.6" } }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -10562,7 +10651,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10607,7 +10695,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -11047,7 +11134,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.1" }, @@ -11059,7 +11145,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -11071,7 +11156,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -11200,6 +11284,14 @@ "integrity": "sha1-B8tKXfJa3Z6Cbrxn3Mn9idsn2Eo=", "dev": true }, + "node_modules/hexy": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", + "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==", + "bin": { + "hexy": "bin/hexy_cmd.js" + } + }, "node_modules/hey-listen": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", @@ -12014,6 +12106,21 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -12115,7 +12222,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12351,7 +12457,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -13330,6 +13435,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbi": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", + "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" + }, "node_modules/jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", @@ -14054,6 +14164,11 @@ "node": ">=8" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/longest-streak": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", @@ -14274,6 +14389,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, "node_modules/map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -14782,6 +14902,16 @@ "node": ">0.9" } }, + "node_modules/mpris-service": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", + "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", + "dependencies": { + "dbus-next": "^0.9.2", + "deep-equal": "^1.0.1", + "source-map-support": "^0.5.11" + } + }, "node_modules/mrmime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", @@ -14809,6 +14939,12 @@ "multicast-dns": "cli.js" } }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -15214,11 +15350,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -15694,6 +15844,14 @@ "node": ">=8" } }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "dependencies": { + "through": "~2.3" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -17787,7 +17945,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -19092,7 +19249,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -19102,7 +19258,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -19205,6 +19360,17 @@ "specificity": "bin/specificity" } }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -19392,6 +19558,14 @@ "node": ">= 0.6" } }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "dependencies": { + "duplexer": "~0.1.1" + } + }, "node_modules/stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", @@ -21375,8 +21549,7 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "node_modules/through2": { "version": "4.0.2", @@ -23455,6 +23628,26 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -24982,6 +25175,11 @@ "fastq": "^1.6.0" } }, + "@nornagon/put": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", + "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==" + }, "@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", @@ -26323,6 +26521,16 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "abstract-socket": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", + "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", + "optional": true, + "requires": { + "bindings": "^1.2.1", + "nan": "^2.12.1" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -27064,6 +27272,15 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -27332,8 +27549,7 @@ "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "builder-util": { "version": "23.6.0", @@ -27507,7 +27723,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -28639,6 +28854,21 @@ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz", "integrity": "sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ==" }, + "dbus-next": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", + "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", + "requires": { + "@nornagon/put": "0.0.8", + "abstract-socket": "^2.0.0", + "event-stream": "3.3.4", + "hexy": "^0.2.10", + "jsbi": "^2.0.5", + "long": "^4.0.0", + "safe-buffer": "^5.1.1", + "xml2js": "^0.4.17" + } + }, "de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -28719,6 +28949,19 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -28764,7 +29007,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dev": true, "requires": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -29114,8 +29356,7 @@ "duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, "duplexer3": { "version": "0.1.4", @@ -30828,6 +31069,20 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -31303,6 +31558,12 @@ "tslib": "^2.4.0" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -31497,6 +31758,11 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -31610,8 +31876,7 @@ "functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, "gauge": { "version": "4.0.4", @@ -31644,7 +31909,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -31985,7 +32249,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, "requires": { "get-intrinsic": "^1.1.1" } @@ -31993,14 +32256,12 @@ "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "requires": { "has-symbols": "^1.0.2" } @@ -32113,6 +32374,11 @@ } } }, + "hexy": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", + "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==" + }, "hey-listen": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", @@ -32713,6 +32979,15 @@ "is-decimal": "^1.0.0" } }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -32787,7 +33062,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, "requires": { "has-tostringtag": "^1.0.0" } @@ -32943,7 +33217,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -33678,6 +33951,11 @@ "argparse": "^2.0.1" } }, + "jsbi": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", + "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" + }, "jsdom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", @@ -34231,6 +34509,11 @@ } } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "longest-streak": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", @@ -34401,6 +34684,11 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -34781,6 +35069,16 @@ "integrity": "sha1-bQUVYRyKjITkhKogABKbmOmB/ws=", "dev": true }, + "mpris-service": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", + "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", + "requires": { + "dbus-next": "^0.9.2", + "deep-equal": "^1.0.1", + "source-map-support": "^0.5.11" + } + }, "mrmime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", @@ -34802,6 +35100,12 @@ "thunky": "^1.0.2" } }, + "nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -35122,11 +35426,19 @@ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "dev": true }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -35484,6 +35796,14 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "requires": { + "through": "~2.3" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -36988,7 +37308,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -38010,7 +38329,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -38019,8 +38337,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -38114,6 +38431,14 @@ "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", "dev": true }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -38263,6 +38588,14 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "requires": { + "duplexer": "~0.1.1" + } + }, "stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", @@ -39818,8 +40151,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "4.0.2", @@ -41383,6 +41715,22 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + } + } + }, "xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", diff --git a/package.json b/package.json index 5ea7b773..99be55e5 100644 --- a/package.json +++ b/package.json @@ -280,6 +280,7 @@ "lodash": "^4.17.21", "md5": "^2.3.0", "memoize-one": "^6.0.0", + "mpris-service": "^2.1.2", "nanoid": "^3.3.3", "net": "^1.0.2", "node-mpv": "^2.0.0-beta.2", diff --git a/release/app/package-lock.json b/release/app/package-lock.json index fc59026f..ee035968 100644 --- a/release/app/package-lock.json +++ b/release/app/package-lock.json @@ -8,7 +8,736 @@ "name": "feishin", "version": "0.0.1-alpha4", "hasInstallScript": true, - "license": "GPL-3.0" + "license": "GPL-3.0", + "dependencies": { + "mpris-service": "^2.1.2" + } + }, + "node_modules/@nornagon/put": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", + "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/abstract-socket": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", + "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ], + "dependencies": { + "bindings": "^1.2.1", + "nan": "^2.12.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dbus-next": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", + "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", + "dependencies": { + "@nornagon/put": "0.0.8", + "event-stream": "3.3.4", + "hexy": "^0.2.10", + "jsbi": "^2.0.5", + "long": "^4.0.0", + "safe-buffer": "^5.1.1", + "xml2js": "^0.4.17" + }, + "optionalDependencies": { + "abstract-socket": "^2.0.0" + } + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hexy": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", + "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==", + "bin": { + "hexy": "bin/hexy_cmd.js" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jsbi": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", + "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, + "node_modules/mpris-service": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", + "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", + "dependencies": { + "dbus-next": "^0.9.2", + "deep-equal": "^1.0.1", + "source-map-support": "^0.5.11" + } + }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "dependencies": { + "duplexer": "~0.1.1" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + } + }, + "dependencies": { + "@nornagon/put": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@nornagon/put/-/put-0.0.8.tgz", + "integrity": "sha512-ugvXJjwF5ldtUpa7D95kruNJ41yFQDEKyF5CW4TgKJnh+W/zmlBzXXeKTyqIgwMFrkePN2JqOBqcF0M0oOunow==" + }, + "abstract-socket": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/abstract-socket/-/abstract-socket-2.1.1.tgz", + "integrity": "sha512-YZJizsvS1aBua5Gd01woe4zuyYBGgSMeqDOB6/ChwdTI904KP6QGtJswXl4hcqWxbz86hQBe++HWV0hF1aGUtA==", + "optional": true, + "requires": { + "bindings": "^1.2.1", + "nan": "^2.12.1" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "dbus-next": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz", + "integrity": "sha512-tzQq/+wrTZ2yU+U5PoeXc97KABhX2v55C/T0finH3tSKYuI8H/SqppIFymBBrUHcK13LvEGY3vdj3ikPPenL5g==", + "requires": { + "@nornagon/put": "0.0.8", + "abstract-socket": "^2.0.0", + "event-stream": "3.3.4", + "hexy": "^0.2.10", + "jsbi": "^2.0.5", + "long": "^4.0.0", + "safe-buffer": "^5.1.1", + "xml2js": "^0.4.17" + } + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hexy": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", + "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==" + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "jsbi": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-2.0.5.tgz", + "integrity": "sha512-TzO/62Hxeb26QMb4IGlI/5X+QLr9Uqp1FPkwp2+KOICW+Q+vSuFj61c8pkT6wAns4WcK56X7CmSHhJeDGWOqxQ==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, + "mpris-service": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", + "integrity": "sha512-AC6WepCnFWwOME9OWplHZ8ps/BB+g9QrEpUKCv7wX82fDPzR3nPrypOFmL/Fm0JloEAu6QTWSfDLLc6mM/jinw==", + "requires": { + "dbus-next": "^0.9.2", + "deep-equal": "^1.0.1", + "source-map-support": "^0.5.11" + } + }, + "nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "requires": { + "through": "~2.3" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "requires": { + "through": "2" + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "requires": { + "duplexer": "~0.1.1" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" } } } diff --git a/release/app/package.json b/release/app/package.json index db32d4c2..8247c3ae 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -12,6 +12,8 @@ "link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.ts", "postinstall": "npm run electron-rebuild && npm run link-modules" }, - "dependencies": {}, + "dependencies": { + "mpris-service": "^2.1.2" + }, "license": "GPL-3.0" } diff --git a/src/main/features/core/player/index.ts b/src/main/features/core/player/index.ts index 8cc89ff1..daba2496 100644 --- a/src/main/features/core/player/index.ts +++ b/src/main/features/core/player/index.ts @@ -1,84 +1,9 @@ import { ipcMain } from 'electron'; -import uniq from 'lodash/uniq'; -import MpvAPI from 'node-mpv'; -import { store } from '../settings'; -import { getMainWindow } from '../../../main'; +import { mpv } from '../../../main'; import { PlayerData } from '/@/renderer/store'; declare module 'node-mpv'; -const BINARY_PATH = store.get('mpv_path') as string | undefined; -const MPV_PARAMETERS = store.get('mpv_parameters') as Array | undefined; -const DEFAULT_MPV_PARAMETERS = () => { - const parameters = []; - if ( - !MPV_PARAMETERS?.includes('--gapless-audio=weak') || - !MPV_PARAMETERS?.includes('--gapless-audio=no') || - !MPV_PARAMETERS?.includes('--gapless-audio=yes') || - !MPV_PARAMETERS?.includes('--gapless-audio') - ) { - parameters.push('--gapless-audio=yes'); - } - - if ( - !MPV_PARAMETERS?.includes('--prefetch-playlist=no') || - !MPV_PARAMETERS?.includes('--prefetch-playlist=yes') || - !MPV_PARAMETERS?.includes('--prefetch-playlist') - ) { - parameters.push('--prefetch-playlist=yes'); - } - - return parameters; -}; - -const mpv = new MpvAPI( - { - audio_only: true, - auto_restart: true, - binary: BINARY_PATH || '', - time_update: 1, - }, - MPV_PARAMETERS - ? uniq([...DEFAULT_MPV_PARAMETERS(), ...MPV_PARAMETERS]) - : DEFAULT_MPV_PARAMETERS(), -); - -mpv.start().catch((error) => { - console.log('error starting mpv', error); -}); - -mpv.on('status', (status) => { - if (status.property === 'playlist-pos') { - if (status.value !== 0) { - getMainWindow()?.webContents.send('renderer-player-auto-next'); - } - } -}); - -// Automatically updates the play button when the player is playing -mpv.on('resumed', () => { - getMainWindow()?.webContents.send('renderer-player-play'); -}); - -// Automatically updates the play button when the player is stopped -mpv.on('stopped', () => { - getMainWindow()?.webContents.send('renderer-player-stop'); -}); - -// Automatically updates the play button when the player is paused -mpv.on('paused', () => { - getMainWindow()?.webContents.send('renderer-player-pause'); -}); - -mpv.on('quit', () => { - console.log('mpv quit'); -}); - -// Event output every interval set by time_update, used to update the current time -mpv.on('timeposition', (time: number) => { - getMainWindow()?.webContents.send('renderer-player-current-time', time); -}); - // Starts the player ipcMain.on('player-play', async () => { await mpv.play(); @@ -161,5 +86,5 @@ ipcMain.on('player-mute', async () => { }); ipcMain.on('player-quit', async () => { - await mpv.quit(); + await mpv.stop(); }); diff --git a/src/main/features/linux/index.ts b/src/main/features/linux/index.ts index e69de29b..01933cbe 100644 --- a/src/main/features/linux/index.ts +++ b/src/main/features/linux/index.ts @@ -0,0 +1 @@ +import './mpris'; diff --git a/src/main/features/linux/mpris.ts b/src/main/features/linux/mpris.ts new file mode 100644 index 00000000..97b439c7 --- /dev/null +++ b/src/main/features/linux/mpris.ts @@ -0,0 +1,168 @@ +import { ipcMain } from 'electron'; +import Player from 'mpris-service'; +import { QueueSong, RelatedArtist } from '../../../renderer/api/types'; +import { getMainWindow } from '../../main'; +import { PlayerRepeat, PlayerShuffle, PlayerStatus } from '/@/renderer/types'; + +const mprisPlayer = Player({ + identity: 'Feishin', + maximumRate: 1.0, + minimumRate: 1.0, + name: 'Feishin', + rate: 1.0, + supportedInterfaces: ['player'], + supportedMimeTypes: ['audio/mpeg', 'application/ogg'], + supportedUriSchemes: ['file'], +}); + +mprisPlayer.on('quit', () => { + process.exit(); +}); + +mprisPlayer.on('stop', () => { + getMainWindow()?.webContents.send('renderer-player-stop'); + mprisPlayer.playbackStatus = 'Paused'; +}); + +mprisPlayer.on('pause', () => { + getMainWindow()?.webContents.send('renderer-player-pause'); + mprisPlayer.playbackStatus = 'Paused'; +}); + +mprisPlayer.on('play', () => { + getMainWindow()?.webContents.send('renderer-player-play'); + mprisPlayer.playbackStatus = 'Playing'; +}); + +mprisPlayer.on('playpause', () => { + getMainWindow()?.webContents.send('renderer-player-play-pause'); + if (mprisPlayer.playbackStatus !== 'Playing') { + mprisPlayer.playbackStatus = 'Playing'; + } else { + mprisPlayer.playbackStatus = 'Paused'; + } +}); + +mprisPlayer.on('next', () => { + getMainWindow()?.webContents.send('renderer-player-next'); + + if (mprisPlayer.playbackStatus !== 'Playing') { + mprisPlayer.playbackStatus = 'Playing'; + } +}); + +mprisPlayer.on('previous', () => { + getMainWindow()?.webContents.send('renderer-player-previous'); + + if (mprisPlayer.playbackStatus !== 'Playing') { + mprisPlayer.playbackStatus = Player.PLAYBACK_STATUS_PLAYING; + } +}); + +mprisPlayer.on('volume', (event: any) => { + getMainWindow()?.webContents.send('mpris-request-volume', { + volume: event, + }); +}); + +mprisPlayer.on('shuffle', (event: boolean) => { + getMainWindow()?.webContents.send('mpris-request-toggle-shuffle', { shuffle: event }); + mprisPlayer.shuffle = event; +}); + +mprisPlayer.on('loopStatus', (event: string) => { + getMainWindow()?.webContents.send('mpris-request-toggle-repeat', { repeat: event }); + mprisPlayer.loopStatus = event; +}); + +mprisPlayer.on('position', (event: any) => { + getMainWindow()?.webContents.send('mpris-request-position', { + position: event.position / 1e6, + }); +}); + +mprisPlayer.on('seek', (event: number) => { + getMainWindow()?.webContents.send('mpris-request-seek', { + offset: event / 1e6, + }); +}); + +ipcMain.on('mpris-update-position', (_event, arg) => { + mprisPlayer.getPosition = () => arg * 1e6; +}); + +ipcMain.on('mpris-update-seek', (_event, arg) => { + mprisPlayer.seeked(arg * 1e6); +}); + +ipcMain.on('mpris-update-volume', (_event, arg) => { + mprisPlayer.volume = Number(arg); +}); + +ipcMain.on('mpris-update-repeat', (_event, arg) => { + mprisPlayer.loopStatus = arg; +}); + +ipcMain.on('mpris-update-shuffle', (_event, arg) => { + mprisPlayer.shuffle = arg; +}); + +ipcMain.on( + 'mpris-update-song', + ( + _event, + args: { + currentTime: number; + repeat: PlayerRepeat; + shuffle: PlayerShuffle; + song: QueueSong; + status: PlayerStatus; + }, + ) => { + const { song, status, repeat, shuffle } = args || {}; + + try { + mprisPlayer.playbackStatus = status; + + if (repeat) { + mprisPlayer.loopStatus = + repeat === 'all' ? 'Playlist' : repeat === 'one' ? 'Track' : 'None'; + } + + if (shuffle) { + mprisPlayer.shuffle = shuffle; + } + + if (!song) return; + + const upsizedImageUrl = song.imageUrl + ? song.imageUrl + ?.replace(/&size=\d+/, '&size=300') + .replace(/\?width=\d+/, '?width=300') + .replace(/&height=\d+/, '&height=300') + : null; + + mprisPlayer.metadata = { + 'mpris:artUrl': upsizedImageUrl, + 'mpris:length': song.duration ? Math.round((song.duration || 0) * 1e6) : null, + 'mpris:trackid': song?.id + ? mprisPlayer.objectPath(`track/${song.id?.replace('-', '')}`) + : '', + 'xesam:album': song.album || null, + 'xesam:albumArtist': song.albumArtists?.length ? song.albumArtists[0].name : null, + 'xesam:artist': + song.artists?.length !== 0 + ? song.artists?.map((artist: RelatedArtist) => artist.name) + : null, + 'xesam:discNumber': song.discNumber ? song.discNumber : null, + 'xesam:genre': song.genres?.length ? song.genres.map((genre: any) => genre.name) : null, + 'xesam:title': song.name || null, + 'xesam:trackNumber': song.trackNumber ? song.trackNumber : null, + 'xesam:useCount': + song.playCount !== null && song.playCount !== undefined ? song.playCount : null, + }; + } catch (err) { + console.log(err); + } + }, +); diff --git a/src/main/main.ts b/src/main/main.ts index 454f3ad8..69092649 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -13,12 +13,16 @@ import { app, BrowserWindow, shell, ipcMain, globalShortcut } from 'electron'; import electronLocalShortcut from 'electron-localshortcut'; import log from 'electron-log'; import { autoUpdater } from 'electron-updater'; +import uniq from 'lodash/uniq'; +import MpvAPI from 'node-mpv'; import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys'; import { store } from './features/core/settings/index'; import MenuBuilder from './menu'; import { resolveHtmlPath } from './utils'; import './features'; +declare module 'node-mpv'; + export default class AppUpdater { constructor() { log.transports.file.level = 'info'; @@ -95,6 +99,7 @@ const createWindow = async () => { ipcMain.on('window-maximize', () => { mainWindow?.maximize(); + mainWindow?.webContents.send('renderer-player-quit'); }); ipcMain.on('window-unmaximize', () => { @@ -142,6 +147,7 @@ const createWindow = async () => { }); mainWindow.on('closed', () => { + // mainWindow?.webContents.send('renderer-player-quit'); mainWindow = null; }); @@ -169,16 +175,88 @@ export const getMainWindow = () => { return mainWindow; }; +const BINARY_PATH = store.get('mpv_path') as string | undefined; +const MPV_PARAMETERS = store.get('mpv_parameters') as Array | undefined; +const DEFAULT_MPV_PARAMETERS = () => { + const parameters = []; + if ( + !MPV_PARAMETERS?.includes('--gapless-audio=weak') || + !MPV_PARAMETERS?.includes('--gapless-audio=no') || + !MPV_PARAMETERS?.includes('--gapless-audio=yes') || + !MPV_PARAMETERS?.includes('--gapless-audio') + ) { + parameters.push('--gapless-audio=yes'); + } + + if ( + !MPV_PARAMETERS?.includes('--prefetch-playlist=no') || + !MPV_PARAMETERS?.includes('--prefetch-playlist=yes') || + !MPV_PARAMETERS?.includes('--prefetch-playlist') + ) { + parameters.push('--prefetch-playlist=yes'); + } + + return parameters; +}; + +export const mpv = new MpvAPI( + { + audio_only: true, + auto_restart: true, + binary: BINARY_PATH || '', + time_update: 1, + }, + MPV_PARAMETERS + ? uniq([...DEFAULT_MPV_PARAMETERS(), ...MPV_PARAMETERS]) + : DEFAULT_MPV_PARAMETERS(), +); + +mpv.start().catch((error) => { + console.log('error starting mpv', error); +}); + +mpv.on('status', (status) => { + if (status.property === 'playlist-pos') { + if (status.value !== 0) { + getMainWindow()?.webContents.send('renderer-player-auto-next'); + } + } +}); + +// Automatically updates the play button when the player is playing +mpv.on('resumed', () => { + getMainWindow()?.webContents.send('renderer-player-play'); +}); + +// Automatically updates the play button when the player is stopped +mpv.on('stopped', () => { + getMainWindow()?.webContents.send('renderer-player-stop'); +}); + +// Automatically updates the play button when the player is paused +mpv.on('paused', () => { + getMainWindow()?.webContents.send('renderer-player-pause'); +}); + +// Event output every interval set by time_update, used to update the current time +mpv.on('timeposition', (time: number) => { + getMainWindow()?.webContents.send('renderer-player-current-time', time); +}); + app.on('before-quit', () => { - mainWindow?.webContents.send('renderer-player-quit'); + mpv.stop(); }); app.on('window-all-closed', () => { + globalShortcut.unregisterAll(); + // Respect the OSX convention of having the application in memory even // after all windows have been closed - globalShortcut.unregisterAll(); if (process.platform !== 'darwin') { app.quit(); + } else { + mpv.stop(); + mainWindow = null; } }); diff --git a/src/main/preload.ts b/src/main/preload.ts index 85f3a083..43a654d9 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -3,7 +3,9 @@ import { PlayerData } from '../renderer/store'; import { browser } from './preload/browser'; import { ipc } from './preload/ipc'; import { localSettings } from './preload/local-settings'; +import { mpris } from './preload/mpris'; import { mpvPlayer, mpvPlayerListener } from './preload/mpv-player'; +import { utils } from './preload/utils'; contextBridge.exposeInMainWorld('electron', { browser, @@ -104,6 +106,8 @@ contextBridge.exposeInMainWorld('electron', { }, }, localSettings, + mpris, mpvPlayer, mpvPlayerListener, + utils, }); diff --git a/src/main/preload/mpris.ts b/src/main/preload/mpris.ts new file mode 100644 index 00000000..eeb84e94 --- /dev/null +++ b/src/main/preload/mpris.ts @@ -0,0 +1,70 @@ +import { IpcRendererEvent, ipcRenderer } from 'electron'; +import { QueueSong } from '/@/renderer/api/types'; + +const updateSong = (args: { currentTime: number; song: QueueSong }) => { + ipcRenderer.send('mpris-update-song', args); +}; + +const updatePosition = (timeSec: number) => { + ipcRenderer.send('mpris-update-position', timeSec); +}; + +const updateSeek = (timeSec: number) => { + ipcRenderer.send('mpris-update-seek', timeSec); +}; + +const updateVolume = (volume: number) => { + ipcRenderer.send('mpris-update-volume', volume); +}; + +const updateRepeat = (repeat: string) => { + ipcRenderer.send('mpris-update-repeat', repeat); +}; + +const updateShuffle = (shuffle: boolean) => { + ipcRenderer.send('mpris-update-shuffle', shuffle); +}; + +const toggleRepeat = () => { + ipcRenderer.send('mpris-toggle-repeat'); +}; + +const toggleShuffle = () => { + ipcRenderer.send('mpris-toggle-shuffle'); +}; + +const requestPosition = (cb: (event: IpcRendererEvent, data: { position: number }) => void) => { + ipcRenderer.on('mpris-request-position', cb); +}; + +const requestSeek = (cb: (event: IpcRendererEvent, data: { offset: number }) => void) => { + ipcRenderer.on('mpris-request-seek', cb); +}; + +const requestVolume = (cb: (event: IpcRendererEvent, data: { volume: number }) => void) => { + ipcRenderer.on('mpris-request-volume', cb); +}; + +const requestToggleRepeat = (cb: (event: IpcRendererEvent) => void) => { + ipcRenderer.on('mpris-request-toggle-repeat', cb); +}; + +const requestToggleShuffle = (cb: (event: IpcRendererEvent) => void) => { + ipcRenderer.on('mpris-request-toggle-shuffle', cb); +}; + +export const mpris = { + requestPosition, + requestSeek, + requestToggleRepeat, + requestToggleShuffle, + requestVolume, + toggleRepeat, + toggleShuffle, + updatePosition, + updateRepeat, + updateSeek, + updateShuffle, + updateSong, + updateVolume, +}; diff --git a/src/main/preload/utils.ts b/src/main/preload/utils.ts new file mode 100644 index 00000000..54c31528 --- /dev/null +++ b/src/main/preload/utils.ts @@ -0,0 +1,7 @@ +import { isMacOS, isWindows, isLinux } from '../utils'; + +export const utils = { + isLinux, + isMacOS, + isWindows, +}; diff --git a/src/renderer/features/action-required/routes/action-required-route.tsx b/src/renderer/features/action-required/routes/action-required-route.tsx index 21511d08..efc2dc42 100644 --- a/src/renderer/features/action-required/routes/action-required-route.tsx +++ b/src/renderer/features/action-required/routes/action-required-route.tsx @@ -24,7 +24,12 @@ const ActionRequiredRoute = () => { const getMpvPath = async () => { if (!isElectron()) return setIsMpvRequired(false); const mpvPath = await localSettings.get('mpv_path'); - return setIsMpvRequired(!mpvPath); + + if (mpvPath) { + return setIsMpvRequired(false); + } + + return setIsMpvRequired(true); }; getMpvPath(); @@ -48,6 +53,8 @@ const ActionRequiredRoute = () => { }, ]; + console.log(checks); + const canReturnHome = checks.every((c) => c.valid); const displayedCheck = checks.find((c) => !c.valid); diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx index 18596fc9..329faaf9 100644 --- a/src/renderer/features/now-playing/components/play-queue.tsx +++ b/src/renderer/features/now-playing/components/play-queue.tsx @@ -34,6 +34,8 @@ import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { QUEUE_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items'; const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; +const utils = isElectron() ? window.electron.utils : null; +const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null; type QueueProps = { type: TableType; @@ -68,6 +70,11 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { const handleDoubleClick = (e: CellDoubleClickedEvent) => { const playerData = setCurrentTrack(e.data.uniqueId); + mpris?.updateSong({ + currentTime: 0, + song: playerData.current.song, + status: 'Playing', + }); if (playerType === PlaybackType.LOCAL) { mpvPlayer.setQueue(playerData); diff --git a/src/renderer/features/player/components/playerbar.tsx b/src/renderer/features/player/components/playerbar.tsx index 4d3e847d..984c2ecc 100644 --- a/src/renderer/features/player/components/playerbar.tsx +++ b/src/renderer/features/player/components/playerbar.tsx @@ -1,4 +1,5 @@ -import { useRef } from 'react'; +import { useCallback, useRef } from 'react'; +import isElectron from 'is-electron'; import styled from 'styled-components'; import { useSettingsStore } from '/@/renderer/store/settings.store'; import { PlaybackType } from '/@/renderer/types'; @@ -50,6 +51,9 @@ const CenterGridItem = styled.div` overflow: hidden; `; +const utils = isElectron() ? window.electron.utils : null; +const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null; + export const Playerbar = () => { const playersRef = useRef(); const settings = useSettingsStore((state) => state.player); @@ -60,6 +64,14 @@ export const Playerbar = () => { const player = useCurrentPlayer(); const { autoNext } = usePlayerControls(); + const autoNextFn = useCallback(() => { + const playerData = autoNext(); + mpris?.updateSong({ + currentTime: 0, + song: playerData.current.song, + }); + }, [autoNext]); + return ( @@ -76,7 +88,7 @@ export const Playerbar = () => { {settings.type === PlaybackType.WEB && ( { const { playersRef } = args; @@ -65,7 +68,27 @@ export const useCenterControls = (args: { playersRef: any }) => { const isMpvPlayer = isElectron() && settings.type === PlaybackType.LOCAL; + const mprisUpdateSong = (args?: { + currentTime?: number; + song?: QueueSong; + status?: PlayerStatus; + }) => { + const { song, currentTime, status } = args || {}; + mpris?.updateSong({ + currentTime: currentTime || usePlayerStore.getState().current.time, + repeat: usePlayerStore.getState().repeat, + shuffle: usePlayerStore.getState().shuffle, + song: song || usePlayerStore.getState().current.song, + status: + (status || usePlayerStore.getState().current.status) === PlayerStatus.PLAYING + ? 'Playing' + : 'Paused', + }); + }; + const handlePlay = useCallback(() => { + mprisUpdateSong({ status: PlayerStatus.PLAYING }); + if (isMpvPlayer) { mpvPlayer.play(); } else { @@ -76,6 +99,8 @@ export const useCenterControls = (args: { playersRef: any }) => { }, [currentPlayerRef, isMpvPlayer, play]); const handlePause = useCallback(() => { + mprisUpdateSong({ status: PlayerStatus.PAUSED }); + if (isMpvPlayer) { mpvPlayer.pause(); } @@ -84,6 +109,8 @@ export const useCenterControls = (args: { playersRef: any }) => { }, [isMpvPlayer, pause]); const handleStop = useCallback(() => { + mprisUpdateSong({ status: PlayerStatus.PAUSED }); + if (isMpvPlayer) { mpvPlayer.stop(); } else { @@ -97,24 +124,29 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleToggleShuffle = useCallback(() => { if (shuffleStatus === PlayerShuffle.NONE) { const playerData = setShuffle(PlayerShuffle.TRACK); + mpris?.updateShuffle(true); return mpvPlayer.setQueueNext(playerData); } const playerData = setShuffle(PlayerShuffle.NONE); + mpris?.updateShuffle(false); return mpvPlayer.setQueueNext(playerData); }, [setShuffle, shuffleStatus]); const handleToggleRepeat = useCallback(() => { if (repeatStatus === PlayerRepeat.NONE) { const playerData = setRepeat(PlayerRepeat.ALL); + mpris?.updateRepeat('Playlist'); return mpvPlayer.setQueueNext(playerData); } if (repeatStatus === PlayerRepeat.ALL) { const playerData = setRepeat(PlayerRepeat.ONE); + mpris?.updateRepeat('Track'); return mpvPlayer.setQueueNext(playerData); } + mpris?.updateRepeat('None'); return setRepeat(PlayerRepeat.NONE); }, [repeatStatus, setRepeat]); @@ -132,11 +164,13 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleRepeatAll = { local: () => { const playerData = autoNext(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.autoNext(playerData); play(); }, web: () => { - autoNext(); + const playerData = autoNext(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); }, }; @@ -144,11 +178,13 @@ export const useCenterControls = (args: { playersRef: any }) => { local: () => { if (isLastTrack) { const playerData = setCurrentIndex(0); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED }); mpvPlayer.setQueue(playerData); mpvPlayer.pause(); pause(); } else { const playerData = autoNext(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.autoNext(playerData); play(); } @@ -156,9 +192,11 @@ export const useCenterControls = (args: { playersRef: any }) => { web: () => { if (isLastTrack) { resetPlayers(); + mprisUpdateSong({ status: PlayerStatus.PAUSED }); pause(); } else { - autoNext(); + const playerData = autoNext(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); } }, @@ -167,14 +205,17 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleRepeatOne = { local: () => { const playerData = autoNext(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.autoNext(playerData); play(); }, web: () => { if (isLastTrack) { + mprisUpdateSong({ status: PlayerStatus.PAUSED }); resetPlayers(); } else { - autoNext(); + const playerData = autoNext(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); } }, @@ -212,11 +253,13 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleRepeatAll = { local: () => { const playerData = next(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.setQueue(playerData); mpvPlayer.next(); }, web: () => { - next(); + const playerData = next(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); }, }; @@ -224,22 +267,26 @@ export const useCenterControls = (args: { playersRef: any }) => { local: () => { if (isLastTrack) { const playerData = setCurrentIndex(0); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED }); mpvPlayer.setQueue(playerData); mpvPlayer.pause(); pause(); } else { const playerData = next(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.setQueue(playerData); mpvPlayer.next(); } }, web: () => { if (isLastTrack) { - setCurrentIndex(0); + const playerData = setCurrentIndex(0); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); pause(); } else { - next(); + const playerData = next(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); } }, @@ -248,12 +295,14 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleRepeatOne = { local: () => { const playerData = next(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.setQueue(playerData); mpvPlayer.next(); }, web: () => { if (!isLastTrack) { - next(); + const playerData = next(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); } }, }; @@ -294,7 +343,7 @@ export const useCenterControls = (args: { playersRef: any }) => { if (currentTime >= 10) { setCurrentTime(0); handleScrobbleFromSongRestart(currentTime); - + mpris?.updateSeek(0); if (isMpvPlayer) { return mpvPlayer.seekTo(0); } @@ -307,20 +356,24 @@ export const useCenterControls = (args: { playersRef: any }) => { local: () => { if (!isFirstTrack) { const playerData = previous(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.setQueue(playerData); mpvPlayer.previous(); } else { const playerData = setCurrentIndex(queue.length - 1); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.setQueue(playerData); mpvPlayer.previous(); } }, web: () => { if (isFirstTrack) { - setCurrentIndex(queue.length - 1); + const playerData = setCurrentIndex(queue.length - 1); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); } else { - previous(); + const playerData = previous(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); } }, @@ -329,15 +382,21 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleRepeatNone = { local: () => { const playerData = previous(); + mpris?.updateSong({ + currentTime: usePlayerStore.getState().current.time, + song: playerData.current.song, + }); mpvPlayer.setQueue(playerData); mpvPlayer.previous(); }, web: () => { if (isFirstTrack) { resetPlayers(); + mprisUpdateSong({ status: PlayerStatus.PAUSED }); pause(); } else { - previous(); + const playerData = previous(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); } }, @@ -347,6 +406,7 @@ export const useCenterControls = (args: { playersRef: any }) => { local: () => { if (!isFirstTrack) { const playerData = previous(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); mpvPlayer.setQueue(playerData); mpvPlayer.previous(); } else { @@ -354,7 +414,8 @@ export const useCenterControls = (args: { playersRef: any }) => { } }, web: () => { - previous(); + const playerData = previous(); + mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING }); resetPlayers(); }, }; @@ -407,14 +468,15 @@ export const useCenterControls = (args: { playersRef: any }) => { ? usePlayerStore.getState().current.time : currentPlayerRef.getCurrentTime(); + const evaluatedTime = currentTime - seconds; + const newTime = evaluatedTime < 0 ? 0 : evaluatedTime; + setCurrentTime(newTime); + mpris?.updateSeek(newTime); + if (isMpvPlayer) { - const newTime = currentTime - seconds; mpvPlayer.seek(-seconds); - setCurrentTime(newTime < 0 ? 0 : newTime); } else { - const newTime = currentTime - seconds; resetNextPlayer(); - setCurrentTime(newTime); currentPlayerRef.seekTo(newTime); } }; @@ -427,12 +489,14 @@ export const useCenterControls = (args: { playersRef: any }) => { if (isMpvPlayer) { const newTime = currentTime + seconds; mpvPlayer.seek(seconds); + mpris?.updateSeek(newTime); setCurrentTime(newTime); } else { const checkNewTime = currentTime + seconds; const songDuration = currentPlayerRef.player.player.duration; const newTime = checkNewTime >= songDuration ? songDuration - 1 : checkNewTime; + mpris?.updateSeek(newTime); resetNextPlayer(); setCurrentTime(newTime); @@ -453,6 +517,8 @@ export const useCenterControls = (args: { playersRef: any }) => { setCurrentTime(e); handleScrobbleFromSeek(e); debouncedSeek(e); + + mpris?.updateSeek(e); }, [debouncedSeek, handleScrobbleFromSeek, setCurrentTime], ); @@ -529,6 +595,93 @@ export const useCenterControls = (args: { playersRef: any }) => { setCurrentTime, ]); + useEffect(() => { + if (utils?.isLinux()) { + const unsubCurrentTime = usePlayerStore.subscribe( + (state) => state.current.time, + (time) => { + mpris?.updatePosition(time); + }, + ); + + return () => { + unsubCurrentTime(); + }; + } + + return () => {}; + }, []); + + useEffect(() => { + if (utils?.isLinux()) { + mpris.requestPosition((_e: any, data: { position: number }) => { + const newTime = data.position; + handleSeekSlider(newTime); + }); + + mpris.requestSeek((_e: any, data: { offset: number }) => { + const currentTime = usePlayerStore.getState().current.time; + const currentSongDuration = usePlayerStore.getState().current.song?.duration || 0; + const resultingTime = currentTime + data.offset; + + let newTime = resultingTime; + if (resultingTime > currentSongDuration) { + newTime = currentSongDuration - 1; + } + + if (resultingTime < 0) { + newTime = 0; + } + + handleSeekSlider(newTime); + }); + + mpris.requestVolume((_e: any, data: { volume: number }) => { + const currentVolume = usePlayerStore.getState().volume; + const resultingVolume = data.volume + currentVolume; + + let newVolume = resultingVolume; + if (newVolume > 100) { + newVolume = 100; + } else if (newVolume < 0) { + newVolume = 0; + } + + usePlayerStore.getState().actions.setVolume(newVolume); + + if (isMpvPlayer) { + mpvPlayer.volume(newVolume); + } + }); + + mpris.requestToggleRepeat((_e: any, data: { repeat: string }) => { + if (data.repeat === 'Playlist') { + usePlayerStore.getState().actions.setRepeat(PlayerRepeat.ALL); + } else if (data.repeat === 'Track') { + usePlayerStore.getState().actions.setRepeat(PlayerRepeat.ONE); + } else { + usePlayerStore.getState().actions.setRepeat(PlayerRepeat.NONE); + } + }); + + mpris.requestToggleShuffle((_e: any, data: { shuffle: boolean }) => { + usePlayerStore + .getState() + .actions.setShuffle(data.shuffle ? PlayerShuffle.TRACK : PlayerShuffle.NONE); + }); + + return () => { + ipc?.removeAllListeners('mpris-request-position'); + ipc?.removeAllListeners('mpris-request-seek'); + ipc?.removeAllListeners('mpris-request-volume'); + ipc?.removeAllListeners('mpris-request-toggle-repeat'); + ipc?.removeAllListeners('mpris-request-toggle-shuffle'); + }; + } + + return () => {}; + }, [handleSeekSlider, isMpvPlayer]); + return { handleNextTrack, handlePlayPause, diff --git a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts index f2cf6b5e..c279c765 100644 --- a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts +++ b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts @@ -20,7 +20,8 @@ import { nanoid } from 'nanoid/non-secure'; import { LibraryItem, SongListSort, SortOrder } from '/@/renderer/api/types'; const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; - +const utils = isElectron() ? window.electron.utils : null; +const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null; export const useHandlePlayQueueAdd = () => { const queryClient = useQueryClient(); const playerType = usePlayerType(); @@ -167,6 +168,13 @@ export const useHandlePlayQueueAdd = () => { if (!songs) return toast.warn({ message: 'No songs found' }); const playerData = usePlayerStore.getState().actions.addToQueue(songs, options.play); + mpris?.updateSong({ + currentTime: usePlayerStore.getState().current.time, + repeat: usePlayerStore.getState().repeat, + shuffle: usePlayerStore.getState().shuffle, + song: playerData.current.song, + status: 'Playing', + }); if (options.play === Play.NEXT || options.play === Play.LAST) { if (playerType === PlaybackType.LOCAL) { diff --git a/src/renderer/preload.d.ts b/src/renderer/preload.d.ts index b5ee2f41..4f39b07a 100644 --- a/src/renderer/preload.d.ts +++ b/src/renderer/preload.d.ts @@ -40,8 +40,10 @@ declare global { windowUnmaximize(): void; }; localSettings: any; + mpris: any; mpvPlayer: any; mpvPlayerListener: any; + utils: any; }; } } diff --git a/src/renderer/router/app-outlet.tsx b/src/renderer/router/app-outlet.tsx index f7f20f14..016b87e2 100644 --- a/src/renderer/router/app-outlet.tsx +++ b/src/renderer/router/app-outlet.tsx @@ -17,7 +17,12 @@ export const AppOutlet = () => { const getMpvPath = async () => { if (!isElectron()) return setIsMpvRequired(false); const mpvPath = await localSettings.get('mpv_path'); - return setIsMpvRequired(!mpvPath); + + if (mpvPath) { + return setIsMpvRequired(false); + } + + return setIsMpvRequired(true); }; getMpvPath(); diff --git a/src/types/mpris-service.d.ts b/src/types/mpris-service.d.ts new file mode 100644 index 00000000..e2669565 --- /dev/null +++ b/src/types/mpris-service.d.ts @@ -0,0 +1 @@ +declare module 'mpris-service';