From bcf53cf9bb870a60f6357e34f43e483213d3575b Mon Sep 17 00:00:00 2001 From: Jean van Kasteel Date: Sun, 10 Nov 2024 19:36:29 +0100 Subject: [PATCH] new feature: DLNA casting - tested working on LG WebOS (B9) - todo: subtitles - todo: cast local files --- app/css/main.css | 15 ++- app/index.html | 14 +++ app/js/config.js | 1 + app/js/lib/cast.js | 80 +++++++++++++++ app/js/main/details.js | 36 +++++++ app/js/utils/boot.js | 13 +++ app/localization/fr.json | 5 +- gulpfile.js | 2 + package-lock.json | 215 +++++++++++++++++++++++++++++++++++++-- package.json | 1 + 10 files changed, 368 insertions(+), 14 deletions(-) create mode 100644 app/js/lib/cast.js diff --git a/app/css/main.css b/app/css/main.css index 1906055..2691ae2 100644 --- a/app/css/main.css +++ b/app/css/main.css @@ -750,13 +750,15 @@ overflow-y: scroll; } -#details-loading .player { +#details-loading .player, +#details-loading .dlnaplayer { font-size: 20px; height: 20%; user-select: none; } -#details-loading .player .control .fa { +#details-loading .player .control .fa, +#details-loading .dlnaplayer .control .fa { background-color: transparent; color: #2b678f; cursor: pointer; @@ -764,16 +766,19 @@ transition: all .5s; } -#details-loading .player .control .fa:hover { +#details-loading .player .control .fa:hover, +#details-loading .dlnaplayer .control .fa:hover { background-color: #2b678f; color: #fafafa; } -#details-loading .player .control .fa-font-small:before { +#details-loading .player .control .fa-font-small:before, +#details-loading .dlnaplayer .control .fa-font-small:before { font-size: 12px; } -#details-loading .player .control .separator { +#details-loading .player .control .separator, +#details-loading .dlnaplayer .control .separator { padding: 0 30px; } diff --git a/app/index.html b/app/index.html index f5cfbf2..4810359 100644 --- a/app/index.html +++ b/app/index.html @@ -622,6 +622,19 @@

My most active day is:

+ +
+
+ DLNA casting +
+
+ no  + +  yes +
@@ -1329,6 +1342,7 @@

Plugins tester

+ diff --git a/app/js/config.js b/app/js/config.js index 3252a48..95fa738 100644 --- a/app/js/config.js +++ b/app/js/config.js @@ -29,6 +29,7 @@ const Nodempv2 = require('node-mpv-2') const Trakttv = require('trakt.tv') const Opensubtitles = require('opensubtitles.com') const Webtorrent = require('webtorrent') +const Dlnacasts = require('dlnacasts2') const PKJSON = require('../package.json') const countryList = require('../app/js/vendor/ISO3166-1.alpha2.json') diff --git a/app/js/lib/cast.js b/app/js/lib/cast.js new file mode 100644 index 0000000..04a29f2 --- /dev/null +++ b/app/js/lib/cast.js @@ -0,0 +1,80 @@ +'use strict' + +const Cast = { + clients: { + dlna: Dlnacasts() + }, + activePlayer: undefined, + players: [], + scan: () => { + // DLNA + Cast.clients.dlna = Dlnacasts() + Cast.clients.dlna.on('update', player => { + //console.info('Found DLNA Device: %s at %s', player.name, player.host) + let exists = false + for (const i in Cast.players) { + if (Cast.players[i].name === player.name) { + exists = true + console.info('Updating the available players list with %s (%s)', player.name, player.host) + Cast.players[i] = { + name: player.name, + url: player.host, + player: player + } + } + } + + if (!exists) { + console.info('Adding %s (%s) to the list of available players', player.name, player.host) + Cast.players.push({ + name: player.name, + url: player.host, + player: player + }) + } + }) + + console.info('Scanning for DLNA devices...') + Cast.clients.dlna.update() + }, + cast: (name, title, url, subtitle) => { + if (Cast.activePlayer) Cast.activePlayer.stop() + + for (const i in Cast.players) { + if (Cast.players[i].name === name) { + const player = Cast.players[i].player + let media = { + title: title, + dlnaFeatures: 'DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01100000000000000000000000000000' + } + if (subtitle) media.subtitte = [subtitle] + player.play(url, media, (err, status) => { + if (err) { + Cast.activePlayer = undefined + } else { + Cast.activePlayer = player + } + }) + } + } + }, + play: () => { + if (Cast.activePlayer) { + console.info('DLNA: play (%s)', Cast.activePlayer.name) + Cast.activePlayer.play() + } + }, + pause: () => { + if (Cast.activePlayer) { + console.info('DLNA: pause (%s)', Cast.activePlayer.name) + Cast.activePlayer.pause() + } + }, + stop: () => { + if (Cast.activePlayer) { + console.info('DLNA: stop (%s)', Cast.activePlayer.name) + Cast.activePlayer.stop() + Cast.activePlayer = undefined + } + } +} \ No newline at end of file diff --git a/app/js/main/details.js b/app/js/main/details.js index d363507..4644820 100644 --- a/app/js/main/details.js +++ b/app/js/main/details.js @@ -174,6 +174,7 @@ const Details = { $(`#${Details.from}`).show() window.scrollTo(0, (Details.fromScroll || 0)) $('#details').hide() + Cast.stop() }, local: { @@ -674,6 +675,26 @@ const Details = { }) }, + keepWatchingDlna: (player) => { + if (Details.from === 'locals') { + $('#keepWatching .message').text(i18n.__('DLNA casting is not allowed on local files')).css('color', '#933') + $('#keepWatching .casting .logo').removeClass('fa-feed').addClass('fa-warning') + $('#keepWatching .casting').show() + $('#keepWatching .selector').hide() + return + } + + $('#keepWatching .message').text(i18n.__('Currently casting to %s', player.name)) + $('#keepWatching .ip').text(player.ip) + $('#keepWatching .casting').show() + $('#keepWatching .selector').hide() + + const title = $('#details-metadata .titles').text().replace(/\W+/g, ' ') + const url = Streamer.streaminfo.url.replace('127.0.0.1', DB.sync.get('localip')) + const subtitle = undefined // todo + Cast.cast(player.name, title, url, subtitle) + }, + keepWatchingPopup: () => { Player.mpv.pause() @@ -683,6 +704,7 @@ const Details = { $('#keepWatching .casting').hide() $('#keepWatching .selector').show() + // add peers for (const i in Network.peers) { const item = `
` + `${Network.peers[i].name}` + @@ -691,6 +713,15 @@ const Details = { '
' $('#keepWatching .selector .list').append(item) } + + // add dlna + for (const i in Cast.players) { + const item = `
` + + `${Cast.players[i].name}` + + `${Cast.players[i].url}` + + `
` + $('#keepWatching .selector .list').append(item) + } $('#keepWatching').show() }, @@ -703,6 +734,11 @@ const Details = { if (DB.sync.get('localsharing') && DB.sync.get('localplayback') && Network.peers.length) { $('#cast .peers').show() } + + // dlna casting + if (DB.sync.get('dlnacasting') && Cast.players.length) { + $('#cast .peers').show() + } }, openFileSelector: (files) => { diff --git a/app/js/utils/boot.js b/app/js/utils/boot.js index 9a96bfb..736a3f2 100644 --- a/app/js/utils/boot.js +++ b/app/js/utils/boot.js @@ -249,6 +249,12 @@ const Boot = { $('#settings .resumeplayback').show() } + // allow DLNA search + if (DB.sync.get('dlnacasting')) { + document.querySelector('#allow_dlnacasting').checked = true + Cast.scan() + } + // allow direct playback feature on local network if (DB.sync.get('localplayback')) { document.querySelector('#allow_resumeplayback').checked = true @@ -350,6 +356,13 @@ const Boot = { } }) + document.querySelector('#allow_dlnacasting').addEventListener('click', (evt) => { + DB.sync.store(evt.target.checked, 'dlnacasting') + if (evt.target.checked) { + Cast.scan() + } + }) + document.querySelector('#allow_resumeplayback').addEventListener('click', (evt) => { DB.sync.store(evt.target.checked, 'localplayback') Network.disconnect() diff --git a/app/localization/fr.json b/app/localization/fr.json index 207229d..2fb77f3 100644 --- a/app/localization/fr.json +++ b/app/localization/fr.json @@ -414,5 +414,8 @@ "Activate the feature and display a 'Rate and review' popup after watching a movie or a show": "Activer la fonctionnalité pour afficher une fenêtre 'Notez et commentez' après avoir regardé un film ou une série", "Default: 55": "Par défaut : 55", "Pin this": "Epingler", - "Game-show": "Jeu télévisé" + "Game-show": "Jeu télévisé", + "DLNA casting": "DLNA casting", + "Cast to DLNA devices on your local network": "Caster via DLNA sur vos périphériques connectés au réseau local", + "DLNA casting is not allowed on local files": "Caster via DLNA n'est pas autorisé avec des fichiers locaux" } \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 7353209..3583167 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -424,6 +424,7 @@ const sd = (fix) => { 'whealth', 'readdirp', 'Webtorrent', + 'Dlnacasts', 'Opensubtitles', 'langs', 'Trakttv', @@ -445,6 +446,7 @@ const sd = (fix) => { 'Local', 'Network', 'Player', + 'Cast', 'Plugins', 'Profiles', 'Search', diff --git a/package-lock.json b/package-lock.json index 72b34eb..54b50b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "auto-launch": "5.0.6", "cheerio": "1.0.0", + "dlnacasts2": "https://github.com/fholzer/dlnacasts2/tree/all-fixes", "fs-extra": "11.2.0", "got": "11.8.6", "i18n": "0.15.1", @@ -2038,7 +2039,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", "integrity": "sha512-afaQKFIg+fob6EzbytOlXZZTYrdZWaegQx2b6AWg9MoALXgctIcbRQrjcu6Wsh5801lVXaQYVwBw6vlATW0qPA==", - "dev": true, "engines": [ "node >= 0.8" ], @@ -2053,14 +2053,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, "license": "MIT" }, "node_modules/concat-stream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -2076,14 +2074,12 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, "license": "MIT" }, "node_modules/concat-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -2152,7 +2148,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, "license": "MIT" }, "node_modules/crc": { @@ -2570,6 +2565,76 @@ "node": ">=8" } }, + "node_modules/dlnacasts2": { + "version": "0.2.0", + "resolved": "git+ssh://git@github.com/fholzer/dlnacasts2.git#624a4f03d8ca96deb404c968720effcdaeca8e4c", + "license": "MIT", + "dependencies": { + "debug": "^2.1.3", + "mime": "^1.3.4", + "node-ssdp": "^2.7.1", + "run-parallel": "^1.1.6", + "simple-get": "^2.1.0", + "thunky": "^0.1.0", + "upnp-mediarenderer-client": "^1.4.0", + "xml2js": "^0.4.8" + } + }, + "node_modules/dlnacasts2/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dlnacasts2/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dlnacasts2/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dlnacasts2/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/dlnacasts2/node_modules/simple-get": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", + "license": "MIT", + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/dlnacasts2/node_modules/thunky": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", + "integrity": "sha512-vquTt/sKNzFqFK8DKLg33U7deg93WKYH4CE2Ul9hOyMCfm7VXgM7GJQRpPAgnmgnrf407Fcq8TQVEKlbavAu+A==" + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2683,6 +2748,18 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -6898,6 +6975,15 @@ "node": ">= 0.4.0" } }, + "node_modules/network-address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/network-address/-/network-address-1.1.2.tgz", + "integrity": "sha512-Q6878fmvItA1mE7H9Il46lONgFgTzX2f98zkS0c2YlkCACzNjwvum/8Kq693IQpxe9zy+w+Zm/4p0wQreLEtZw==", + "license": "MIT", + "bin": { + "network-address": "cli.js" + } + }, "node_modules/next-event": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-event/-/next-event-1.0.0.tgz", @@ -6979,6 +7065,40 @@ "resolved": "https://registry.npmjs.org/node-mpv-2/-/node-mpv-2-2.0.0-beta.3.tgz", "integrity": "sha512-R4G2YjTTk5R6cENosvpLhjVC5RrooPZrY/UsszPWv8Xom56MZFYsen9hyIJIGl6K5OJyuGla8jsF98xsUQKExA==" }, + "node_modules/node-ssdp": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/node-ssdp/-/node-ssdp-2.9.1.tgz", + "integrity": "sha512-yGUSsm7HKxcv1XU0X6BIMWaOl/SaXqrIhwZCdklmAzwjG6qt+hnJwzs+VigCuRMP+jhSyoVBvHnoc95VgxbcuQ==", + "license": "MIT", + "dependencies": { + "debug": "^2.2.0", + "ip": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-ssdp/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/node-ssdp/node_modules/ip": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "license": "MIT" + }, + "node_modules/node-ssdp/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/node-stream-zip": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", @@ -8333,7 +8453,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, "license": "MIT" }, "node_modules/progress": { @@ -9071,6 +9190,12 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "license": "ISC" + }, "node_modules/semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -10606,7 +10731,6 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, "license": "MIT" }, "node_modules/typedarray-to-buffer": { @@ -11020,6 +11144,59 @@ "node": ">=4" } }, + "node_modules/upnp-device-client": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/upnp-device-client/-/upnp-device-client-1.0.2.tgz", + "integrity": "sha512-5BcYJJU5wXR6xGko/UuLSavybAA0sZx17Hka4ikOXwA9Ze3fiExmgUDytAXE5qjdbKzARl0lOLC3hPSUwAa3eQ==", + "license": "MIT", + "dependencies": { + "concat-stream": "^1.4.8", + "debug": "^2.1.3", + "elementtree": "~0.1.6", + "network-address": "^1.0.0" + } + }, + "node_modules/upnp-device-client/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/upnp-device-client/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/upnp-mediarenderer-client": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/upnp-mediarenderer-client/-/upnp-mediarenderer-client-1.4.0.tgz", + "integrity": "sha512-F+C3Yceoz0j3ZWEchz5tpaOEqkbpObRUmeuPGc9+2u2YvC1CDbXGQ6mjbM10MDhnUJ0tTWYTufpj6xsWctnULw==", + "license": "MIT", + "dependencies": { + "debug": "^2.1.3", + "elementtree": "^0.1.6", + "upnp-device-client": "^1.0.0" + } + }, + "node_modules/upnp-mediarenderer-client/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/upnp-mediarenderer-client/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -11908,6 +12085,28 @@ "node": ">=8" } }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", diff --git a/package.json b/package.json index 711c2b4..e7d037b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "dependencies": { "auto-launch": "5.0.6", "cheerio": "1.0.0", + "dlnacasts2": "https://github.com/fholzer/dlnacasts2/tree/all-fixes", "fs-extra": "11.2.0", "got": "11.8.6", "i18n": "0.15.1",