mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-07 12:07:09 +03:00
Merge with LMS OTA proxy
This commit is contained in:
@@ -13,7 +13,7 @@ But squeezelite-esp32 is highly extensible and you can add
|
||||
|
||||
- Buttons and Rotary Encoder and map/combine them to various functions (play, pause, volume, next ...)
|
||||
- IR receiver (no pullup resistor or capacitor needed, just the 38kHz receiver)
|
||||
- Monochrome, GrayScale or Color displays using SPI or I2S (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and IL9341).
|
||||
- Monochrome, GrayScale or Color displays using SPI or I2C (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and ILI9341).
|
||||
|
||||
Other features include
|
||||
|
||||
@@ -172,7 +172,7 @@ Ground -------------------------- coax signal ground
|
||||
The NVS parameter "display_config" sets the parameters for an optional display. Syntax is
|
||||
```
|
||||
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
|
||||
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789[,rotate]]
|
||||
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789|ILI9341[:16|18][,rotate]]
|
||||
```
|
||||
- back: a LED backlight used by some older devices (ST7735). It is PWM controlled for brightness
|
||||
- reset: some display have a reset pin that is should normally be pulled up if unused
|
||||
@@ -188,7 +188,7 @@ SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed
|
||||
- SSD1675 is an e-ink paper and is experimental as e-ink is really not suitable for LMS du to its very low refresh rate
|
||||
- ST7735 is a 128x160 65k color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/1.8inch-lcd-module.htm). This needs a backlight control
|
||||
- ST7789 is a 240x320 65k (262k not enabled) color SPI [here](https://www.waveshare.com/product/displays/lcd-oled/lcd-oled-3/2inch-lcd-module.htm). It also exist with 240x240 displays. See **rotate** for use in portrait mode
|
||||
- IL9341 is another 240x320 65k (262k capable) color SPI. I've not used it much, the driver it has been provided by one external contributor to the project
|
||||
- ILI9341 is another 240x320 65k (262k capable) color SPI. I've not used it much, the driver it has been provided by one external contributor to the project
|
||||
|
||||
To use the display on LMS, add repository https://raw.githubusercontent.com/sle118/squeezelite-esp32/master/plugin/repo.xml. You will then be able to tweak how the vu-meter and spectrum analyzer are displayed, as well as size of artwork. You can also install the excellent plugin "Music Information Screen" which is super useful to tweak the layout.
|
||||
|
||||
|
||||
@@ -14,5 +14,8 @@
|
||||
"ssid": "MyTestSSID",
|
||||
"ip": "192.168.10.225",
|
||||
"netmask": "255.255.255.0",
|
||||
"gw": "192.168.10.1"
|
||||
"gw": "192.168.10.1",
|
||||
"lms_cport": 9090,
|
||||
"lms_port": 9000,
|
||||
"lms_ip": "127.0.0.1"
|
||||
}
|
||||
@@ -550,6 +550,7 @@ let project_name=versionName;
|
||||
let btSinkNamesOptSel='#cfg-audio-bt_source-sink_name';
|
||||
let ConnectedToSSID={};
|
||||
let ConnectingToSSID={};
|
||||
let lmsBaseUrl;
|
||||
const ConnectingToActions = {
|
||||
'CONN' : 0,'MAN' : 1,'STS' : 2,
|
||||
}
|
||||
@@ -1315,8 +1316,7 @@ $(document).ready(function() {
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
window.setURL = function(button) {
|
||||
const url = button.dataset.url;
|
||||
$('#fwurl').val(url);
|
||||
let url = button.dataset.url;
|
||||
|
||||
$('[data-url^="http"]')
|
||||
.addClass('btn-success')
|
||||
@@ -1324,6 +1324,13 @@ window.setURL = function(button) {
|
||||
$('[data-url="' + url + '"]')
|
||||
.addClass('btn-danger')
|
||||
.removeClass('btn-success');
|
||||
|
||||
// if user can proxy download through LMS, modify the URL
|
||||
if (lmsBaseUrl) {
|
||||
url = url.replace(/.*\/download\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');
|
||||
}
|
||||
|
||||
$('#fwurl').val(url);
|
||||
}
|
||||
|
||||
// function performConnect(conntype) {
|
||||
@@ -1764,6 +1771,20 @@ function checkStatus() {
|
||||
$('#battery').hide();
|
||||
}
|
||||
|
||||
if (typeof lmsBaseUrl == "undefined" && data.lms_ip && data.lms_port) {
|
||||
const baseUrl = 'http://' + data.lms_ip + ':' + data.lms_port;
|
||||
$.ajax({
|
||||
url: baseUrl + '/plugins/SqueezeESP32/firmware/-99',
|
||||
error: function() {
|
||||
// define the value, so we don't check it any more.
|
||||
lmsBaseUrl = '';
|
||||
},
|
||||
success: function() {
|
||||
lmsBaseUrl = baseUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#o_jack').attr('display', Number(data.Jack) ? 'inline' : 'none');
|
||||
blockAjax = false;
|
||||
}).fail(function(xhr, ajaxOptions, thrownError) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/favicon-32x32.png BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/index.html.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/index.31a52e.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/node-modules.31a52e.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/runtime.31a52e.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/index.0b6890.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/node-modules.0b6890.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager ./webapp/webpack/dist/js/runtime.0b6890.bundle.js.gz BINARY)
|
||||
|
||||
@@ -4,6 +4,7 @@ extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_s
|
||||
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
|
||||
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
|
||||
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
|
||||
<<<<<<< HEAD
|
||||
extern const uint8_t _index_31a52e_bundle_js_gz_start[] asm("_binary_index_31a52e_bundle_js_gz_start");
|
||||
extern const uint8_t _index_31a52e_bundle_js_gz_end[] asm("_binary_index_31a52e_bundle_js_gz_end");
|
||||
extern const uint8_t _node_modules_31a52e_bundle_js_gz_start[] asm("_binary_node_modules_31a52e_bundle_js_gz_start");
|
||||
@@ -16,19 +17,45 @@ const char * resource_lookups[] = {
|
||||
"/js/index.31a52e.bundle.js.gz",
|
||||
"/js/node-modules.31a52e.bundle.js.gz",
|
||||
"/js/runtime.31a52e.bundle.js.gz",
|
||||
=======
|
||||
extern const uint8_t _index_0b6890_bundle_js_gz_start[] asm("_binary_index_0b6890_bundle_js_gz_start");
|
||||
extern const uint8_t _index_0b6890_bundle_js_gz_end[] asm("_binary_index_0b6890_bundle_js_gz_end");
|
||||
extern const uint8_t _node_modules_0b6890_bundle_js_gz_start[] asm("_binary_node_modules_0b6890_bundle_js_gz_start");
|
||||
extern const uint8_t _node_modules_0b6890_bundle_js_gz_end[] asm("_binary_node_modules_0b6890_bundle_js_gz_end");
|
||||
extern const uint8_t _runtime_0b6890_bundle_js_gz_start[] asm("_binary_runtime_0b6890_bundle_js_gz_start");
|
||||
extern const uint8_t _runtime_0b6890_bundle_js_gz_end[] asm("_binary_runtime_0b6890_bundle_js_gz_end");
|
||||
const char * resource_lookups[] = {
|
||||
"/dist/favicon-32x32.png",
|
||||
"/dist/index.html.gz",
|
||||
"/js/index.0b6890.bundle.js.gz",
|
||||
"/js/node-modules.0b6890.bundle.js.gz",
|
||||
"/js/runtime.0b6890.bundle.js.gz",
|
||||
>>>>>>> master-cmake
|
||||
""
|
||||
};
|
||||
const uint8_t * resource_map_start[] = {
|
||||
_favicon_32x32_png_start,
|
||||
_index_html_gz_start,
|
||||
<<<<<<< HEAD
|
||||
_index_31a52e_bundle_js_gz_start,
|
||||
_node_modules_31a52e_bundle_js_gz_start,
|
||||
_runtime_31a52e_bundle_js_gz_start
|
||||
=======
|
||||
_index_0b6890_bundle_js_gz_start,
|
||||
_node_modules_0b6890_bundle_js_gz_start,
|
||||
_runtime_0b6890_bundle_js_gz_start
|
||||
>>>>>>> master-cmake
|
||||
};
|
||||
const uint8_t * resource_map_end[] = {
|
||||
_favicon_32x32_png_end,
|
||||
_index_html_gz_end,
|
||||
<<<<<<< HEAD
|
||||
_index_31a52e_bundle_js_gz_end,
|
||||
_node_modules_31a52e_bundle_js_gz_end,
|
||||
_runtime_31a52e_bundle_js_gz_end
|
||||
=======
|
||||
_index_0b6890_bundle_js_gz_end,
|
||||
_node_modules_0b6890_bundle_js_gz_end,
|
||||
_runtime_0b6890_bundle_js_gz_end
|
||||
>>>>>>> master-cmake
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/***********************************
|
||||
webpack_headers
|
||||
<<<<<<< HEAD
|
||||
Hash: 31a52ecfe661f5a02717
|
||||
Version: webpack 4.44.2
|
||||
Time: 6575ms
|
||||
@@ -38,11 +39,52 @@ Entrypoint index [big] = ./js/runtime.31a52e.bundle.js ./js/node-modules.31a52e.
|
||||
[37] ./src/index.ts + 1 modules 59.9 KiB {0} [built]
|
||||
| ./src/index.ts 1.36 KiB [built]
|
||||
| ./src/js/custom.js 58.4 KiB [built]
|
||||
=======
|
||||
Hash: 0b6890f4337e767921f7
|
||||
Version: webpack 4.46.0
|
||||
Time: 273269ms
|
||||
Built at: 2021-04-03 1:28:56
|
||||
Asset Size Chunks Chunk Names
|
||||
./js/index.0b6890.bundle.js 231 KiB 0 [emitted] [immutable] index
|
||||
./js/index.0b6890.bundle.js.br 31.5 KiB [emitted]
|
||||
./js/index.0b6890.bundle.js.gz 41.1 KiB [emitted]
|
||||
./js/node-modules.0b6890.bundle.js 266 KiB 1 [emitted] [immutable] [big] node-modules
|
||||
./js/node-modules.0b6890.bundle.js.br 76.3 KiB [emitted]
|
||||
./js/node-modules.0b6890.bundle.js.gz 88.7 KiB [emitted]
|
||||
./js/runtime.0b6890.bundle.js 1.46 KiB 2 [emitted] [immutable] runtime
|
||||
./js/runtime.0b6890.bundle.js.br 644 bytes [emitted]
|
||||
./js/runtime.0b6890.bundle.js.gz 722 bytes [emitted]
|
||||
favicon-32x32.png 634 bytes [emitted]
|
||||
index.html 19.5 KiB [emitted]
|
||||
index.html.br 4.48 KiB [emitted]
|
||||
index.html.gz 5.46 KiB [emitted]
|
||||
sprite.svg 4.4 KiB [emitted]
|
||||
sprite.svg.br 912 bytes [emitted]
|
||||
Entrypoint index [big] = ./js/runtime.0b6890.bundle.js ./js/node-modules.0b6890.bundle.js ./js/index.0b6890.bundle.js
|
||||
[6] ./node_modules/bootstrap/dist/js/bootstrap-exposed.js 437 bytes {1} [built]
|
||||
[11] ./src/sass/main.scss 1.55 KiB {0} [built]
|
||||
[16] ./node_modules/remixicon/icons/Device/signal-wifi-fill.svg 323 bytes {1} [built]
|
||||
[17] ./node_modules/remixicon/icons/Device/signal-wifi-3-fill.svg 327 bytes {1} [built]
|
||||
[18] ./node_modules/remixicon/icons/Device/signal-wifi-2-fill.svg 327 bytes {1} [built]
|
||||
[19] ./node_modules/remixicon/icons/Device/signal-wifi-1-fill.svg 327 bytes {1} [built]
|
||||
[20] ./node_modules/remixicon/icons/Device/signal-wifi-line.svg 323 bytes {1} [built]
|
||||
[21] ./node_modules/remixicon/icons/Device/battery-line.svg 315 bytes {1} [built]
|
||||
[22] ./node_modules/remixicon/icons/Device/battery-low-line.svg 323 bytes {1} [built]
|
||||
[23] ./node_modules/remixicon/icons/Device/battery-fill.svg 315 bytes {1} [built]
|
||||
[24] ./node_modules/remixicon/icons/Media/headphone-fill.svg 318 bytes {1} [built]
|
||||
[25] ./node_modules/remixicon/icons/Device/device-recover-fill.svg 329 bytes {1} [built]
|
||||
[26] ./node_modules/remixicon/icons/Device/bluetooth-fill.svg 319 bytes {1} [built]
|
||||
[27] ./node_modules/remixicon/icons/Device/bluetooth-connect-fill.svg 335 bytes {1} [built]
|
||||
[37] ./src/index.ts + 1 modules 53.3 KiB {0} [built]
|
||||
| ./src/index.ts 1.36 KiB [built]
|
||||
| ./src/js/custom.js 51.8 KiB [built]
|
||||
>>>>>>> master-cmake
|
||||
+ 23 hidden modules
|
||||
|
||||
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
|
||||
This can impact web performance.
|
||||
Assets:
|
||||
<<<<<<< HEAD
|
||||
./js/node-modules.31a52e.bundle.js (265 KiB)
|
||||
|
||||
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
|
||||
@@ -51,6 +93,16 @@ Entrypoints:
|
||||
./js/runtime.31a52e.bundle.js
|
||||
./js/node-modules.31a52e.bundle.js
|
||||
./js/index.31a52e.bundle.js
|
||||
=======
|
||||
./js/node-modules.0b6890.bundle.js (266 KiB)
|
||||
|
||||
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
|
||||
Entrypoints:
|
||||
index (499 KiB)
|
||||
./js/runtime.0b6890.bundle.js
|
||||
./js/node-modules.0b6890.bundle.js
|
||||
./js/index.0b6890.bundle.js
|
||||
>>>>>>> master-cmake
|
||||
|
||||
|
||||
WARNING in webpack performance recommendations:
|
||||
@@ -60,8 +112,13 @@ Child html-webpack-plugin for "index.html":
|
||||
Asset Size Chunks Chunk Names
|
||||
index.html 558 KiB 0
|
||||
Entrypoint undefined = index.html
|
||||
<<<<<<< HEAD
|
||||
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.ejs 23.7 KiB {0} [built]
|
||||
[1] ./node_modules/lodash/lodash.js 530 KiB {0} [built]
|
||||
=======
|
||||
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.ejs 20.3 KiB {0} [built]
|
||||
[1] ./node_modules/lodash/lodash.js 531 KiB {0} [built]
|
||||
>>>>>>> master-cmake
|
||||
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
|
||||
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
|
||||
***********************************/
|
||||
|
||||
BIN
components/wifi-manager/webapp/webpack/dist/favicon-32x32.png
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/favicon-32x32.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
1
components/wifi-manager/webapp/webpack/dist/index.html
vendored
Normal file
1
components/wifi-manager/webapp/webpack/dist/index.html
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
components/wifi-manager/webapp/webpack/dist/index.html.br
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/index.html.br
vendored
Normal file
Binary file not shown.
BIN
components/wifi-manager/webapp/webpack/dist/index.html.gz
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/index.html.gz
vendored
Normal file
Binary file not shown.
9
components/wifi-manager/webapp/webpack/dist/js/index.0b6890.bundle.js
vendored
Normal file
9
components/wifi-manager/webapp/webpack/dist/js/index.0b6890.bundle.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0b6890.bundle.js.br
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0b6890.bundle.js.br
vendored
Normal file
Binary file not shown.
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0b6890.bundle.js.gz
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/index.0b6890.bundle.js.gz
vendored
Normal file
Binary file not shown.
63
components/wifi-manager/webapp/webpack/dist/js/node-modules.0b6890.bundle.js
vendored
Normal file
63
components/wifi-manager/webapp/webpack/dist/js/node-modules.0b6890.bundle.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
components/wifi-manager/webapp/webpack/dist/js/node-modules.0b6890.bundle.js.br
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/node-modules.0b6890.bundle.js.br
vendored
Normal file
Binary file not shown.
BIN
components/wifi-manager/webapp/webpack/dist/js/node-modules.0b6890.bundle.js.gz
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/node-modules.0b6890.bundle.js.gz
vendored
Normal file
Binary file not shown.
1
components/wifi-manager/webapp/webpack/dist/js/runtime.0b6890.bundle.js
vendored
Normal file
1
components/wifi-manager/webapp/webpack/dist/js/runtime.0b6890.bundle.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e){function r(r){for(var n,l,f=r[0],i=r[1],a=r[2],c=0,s=[];c<f.length;c++)l=f[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,a||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,f=1;f<t.length;f++){var i=t[f];0!==o[i]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={2:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="";var f=window.webpackJsonp=window.webpackJsonp||[],i=f.push.bind(f);f.push=r,f=f.slice();for(var a=0;a<f.length;a++)r(f[a]);var p=i;t()}([]);
|
||||
BIN
components/wifi-manager/webapp/webpack/dist/js/runtime.0b6890.bundle.js.br
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/runtime.0b6890.bundle.js.br
vendored
Normal file
Binary file not shown.
BIN
components/wifi-manager/webapp/webpack/dist/js/runtime.0b6890.bundle.js.gz
vendored
Normal file
BIN
components/wifi-manager/webapp/webpack/dist/js/runtime.0b6890.bundle.js.gz
vendored
Normal file
Binary file not shown.
@@ -111,7 +111,7 @@ module.exports = merge(common, {
|
||||
contentBase: path.join(__dirname, 'dist'),
|
||||
publicPath: '/',
|
||||
port: 9100,
|
||||
host: 'desktop-n8u8515',//your ip address
|
||||
host: '127.0.0.1',//your ip address
|
||||
disableHostCheck: true,
|
||||
headers: {'Access-Control-Allow-Origin': '*',
|
||||
'Accept-Encoding': 'identity'},
|
||||
|
||||
@@ -3,6 +3,9 @@ package Plugins::SqueezeESP32::Plugin;
|
||||
use strict;
|
||||
|
||||
use base qw(Slim::Plugin::Base);
|
||||
use File::Basename qw(basename);
|
||||
use File::Spec::Functions qw(catfile);
|
||||
use JSON::XS::VersionOneAndTwo;
|
||||
|
||||
use Slim::Utils::Prefs;
|
||||
use Slim::Utils::Log;
|
||||
@@ -16,6 +19,12 @@ my $log = Slim::Utils::Log->addLogCategory({
|
||||
'description' => 'PLUGIN_SQUEEZEESP32',
|
||||
});
|
||||
|
||||
use constant GITHUB_ASSET_URI => "https://api.github.com/repos/sle118/squeezelite-esp32/releases/assets/";
|
||||
use constant GITHUB_DOWNLOAD_URI => "https://github.com/sle118/squeezelite-esp32/releases/download/";
|
||||
my $FW_DOWNLOAD_ID_REGEX = qr|plugins/SqueezeESP32/firmware/(-?\d+)|;
|
||||
my $FW_DOWNLOAD_REGEX = qr|plugins/SqueezeESP32/firmware/([-a-z0-9-/.]+\.bin)$|i;
|
||||
my $FW_FILENAME_REGEX = qr/^squeezelite-esp32-.*\.bin(\.tmp)?$/;
|
||||
|
||||
# migrate 'eq' pref, as that's a reserved word and could cause problems in the future
|
||||
$prefs->migrateClient(1, sub {
|
||||
my ($cprefs, $client) = @_;
|
||||
@@ -58,6 +67,9 @@ sub initPlugin {
|
||||
Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['newmetadata'] ] );
|
||||
Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['playlist'], ['open', 'newsong'] ]);
|
||||
Slim::Control::Request::subscribe( \&onStopClear, [ ['playlist'], ['stop', 'clear'] ]);
|
||||
|
||||
Slim::Web::Pages->addRawFunction($FW_DOWNLOAD_ID_REGEX, \&handleFirmwareDownload);
|
||||
Slim::Web::Pages->addRawFunction($FW_DOWNLOAD_REGEX, \&handleFirmwareDownloadDirect);
|
||||
}
|
||||
|
||||
sub onStopClear {
|
||||
@@ -99,4 +111,137 @@ sub setEQ {
|
||||
$client->send_equalizer(\@eqParams);
|
||||
}
|
||||
|
||||
sub handleFirmwareDownload {
|
||||
my ($httpClient, $response) = @_;
|
||||
|
||||
my $request = $response->request;
|
||||
|
||||
my $_errorDownloading = sub {
|
||||
_errorDownloading($httpClient, $response, @_);
|
||||
};
|
||||
|
||||
my $id;
|
||||
if (!defined $request || !(($id) = $request->uri =~ $FW_DOWNLOAD_ID_REGEX)) {
|
||||
return $_errorDownloading->(undef, 'Invalid request', $request->uri, 400);
|
||||
}
|
||||
|
||||
# this is the magic number used on the client to figure out whether the plugin does support download proxying
|
||||
if ($id == -99) {
|
||||
$response->code(204);
|
||||
$response->header('Access-Control-Allow-Origin' => '*');
|
||||
|
||||
$httpClient->send_response($response);
|
||||
return Slim::Web::HTTP::closeHTTPSocket($httpClient);
|
||||
}
|
||||
|
||||
Slim::Networking::SimpleAsyncHTTP->new(
|
||||
sub {
|
||||
my $http = shift;
|
||||
my $content = eval { from_json( $http->content ) };
|
||||
|
||||
if (!$content || !ref $content) {
|
||||
$@ && $log->error("Failed to parse response: $@");
|
||||
return $_errorDownloading->($http);
|
||||
}
|
||||
elsif (!$content->{browser_download_url} || !$content->{name}) {
|
||||
return $_errorDownloading->($http, 'No download URL found');
|
||||
}
|
||||
|
||||
downloadAndStreamFirmware($httpClient, $response, $content->{browser_download_url}, $content->{name});
|
||||
},
|
||||
$_errorDownloading,
|
||||
{
|
||||
timeout => 10,
|
||||
cache => 1,
|
||||
expires => 86400
|
||||
}
|
||||
)->get(GITHUB_ASSET_URI . $id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub handleFirmwareDownloadDirect {
|
||||
my ($httpClient, $response) = @_;
|
||||
|
||||
my $request = $response->request;
|
||||
|
||||
my $_errorDownloading = sub {
|
||||
_errorDownloading($httpClient, $response, @_);
|
||||
};
|
||||
|
||||
my $path;
|
||||
if (!defined $request || !(($path) = $request->uri =~ $FW_DOWNLOAD_REGEX)) {
|
||||
return $_errorDownloading->(undef, 'Invalid request', $request->uri, 400);
|
||||
}
|
||||
|
||||
main::INFOLOG && $log->is_info && $log->info("Requesting firmware from: $path");
|
||||
|
||||
downloadAndStreamFirmware($httpClient, $response, GITHUB_DOWNLOAD_URI . $path);
|
||||
}
|
||||
|
||||
sub downloadAndStreamFirmware {
|
||||
my ($httpClient, $response, $url, $name) = @_;
|
||||
|
||||
my $_errorDownloading = sub {
|
||||
_errorDownloading($httpClient, $response, @_);
|
||||
};
|
||||
|
||||
$name ||= basename($url);
|
||||
|
||||
if ($name !~ $FW_FILENAME_REGEX) {
|
||||
return $_errorDownloading->(undef, 'Unexpected firmware image name: ' . $name, $url, 400);
|
||||
}
|
||||
|
||||
my $updatesDir = Slim::Utils::OSDetect::dirsFor('updates');
|
||||
my $firmwareFile = catfile($updatesDir, $name);
|
||||
Slim::Utils::Misc::deleteFiles($updatesDir, $FW_FILENAME_REGEX, $firmwareFile);
|
||||
|
||||
if (-f $firmwareFile) {
|
||||
main::INFOLOG && $log->is_info && $log->info("Found cached firmware version");
|
||||
$response->code(200);
|
||||
return Slim::Web::HTTP::sendStreamingFile($httpClient, $response, 'application/octet-stream', $firmwareFile, undef, 1);
|
||||
}
|
||||
|
||||
Slim::Networking::SimpleAsyncHTTP->new(
|
||||
sub {
|
||||
my $http = shift;
|
||||
|
||||
if ($http->code != 200 || !-e "$firmwareFile.tmp") {
|
||||
return $_errorDownloading->($http, $http->mess);
|
||||
}
|
||||
|
||||
rename "$firmwareFile.tmp", $firmwareFile or return $_errorDownloading->($http, "Unable to rename temporary $firmwareFile file" );
|
||||
|
||||
$response->code(200);
|
||||
Slim::Web::HTTP::sendStreamingFile($httpClient, $response, 'application/octet-stream', $firmwareFile, undef, 1);
|
||||
},
|
||||
$_errorDownloading,
|
||||
{
|
||||
saveAs => "$firmwareFile.tmp",
|
||||
}
|
||||
)->get($url);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub _errorDownloading {
|
||||
my ($httpClient, $response, $http, $error, $url, $code) = @_;
|
||||
|
||||
$error ||= ($http && $http->error) || 'unknown error';
|
||||
$url ||= ($http && $http->url) || 'no URL';
|
||||
$code ||= ($http && $http->code) || 500;
|
||||
|
||||
$log->error(sprintf("Failed to get data from Github: %s (%s)", $error || $http->error, $url));
|
||||
|
||||
$response->headers->remove_content_headers;
|
||||
$response->code($code);
|
||||
$response->content_type('text/plain');
|
||||
$response->header('Connection' => 'close');
|
||||
$response->content('');
|
||||
|
||||
$httpClient->send_response($response);
|
||||
Slim::Web::HTTP::closeHTTPSocket($httpClient);
|
||||
};
|
||||
|
||||
|
||||
1;
|
||||
|
||||
1
server_certs/getcert.sh
Normal file → Executable file
1
server_certs/getcert.sh
Normal file → Executable file
@@ -45,3 +45,4 @@ get_all_pem github.com github-com
|
||||
get_all_pem s3.amazonaws.com s3-amazon-com
|
||||
get_all_pem github-releases.githubusercontent.com githubusercontent-com
|
||||
cat *.pem >github.pem
|
||||
|
||||
|
||||
Reference in New Issue
Block a user