mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-06-10 14:27:44 +01: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) {
|
||||
@@ -1763,6 +1770,20 @@ function checkStatus() {
|
||||
} else {
|
||||
$('#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;
|
||||
|
||||
@@ -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]
|
||||
***********************************/
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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()}([]);
|
||||
Binary file not shown.
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) = @_;
|
||||
@@ -48,7 +57,7 @@ sub initPlugin {
|
||||
$class->SUPER::initPlugin(@_);
|
||||
# no name can be a subset of others due to a bug in addPlayerClass
|
||||
Slim::Networking::Slimproto::addPlayerClass($class, 100, 'squeezeesp32-basic', { client => 'Plugins::SqueezeESP32::Player', display => 'Plugins::SqueezeESP32::Graphics' });
|
||||
Slim::Networking::Slimproto::addPlayerClass($class, 101, 'squeezeesp32-graphic', { client => 'Plugins::SqueezeESP32::Player', display => 'Slim::Display::NoDisplay' });
|
||||
Slim::Networking::Slimproto::addPlayerClass($class, 101, 'squeezeesp32-graphic', { client => 'Plugins::SqueezeESP32::Player', display => 'Slim::Display::NoDisplay' });
|
||||
main::INFOLOG && $log->is_info && $log->info("Added class 100 and 101 for SqueezeESP32");
|
||||
|
||||
# register a command to set the EQ - without saving the values! Send params as single comma separated list of values
|
||||
@@ -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;
|
||||
|
||||
Regular → Executable
+1
@@ -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