mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-31 21:59:43 +03:00
Compare commits
9 Commits
SqueezeAmp
...
SqueezeAmp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c143ea56ff | ||
|
|
3fc7e68163 | ||
|
|
2dea2ca08c | ||
|
|
2584026e5c | ||
|
|
f2b0c40848 | ||
|
|
1876b26100 | ||
|
|
f84e856e68 | ||
|
|
34fa7203be | ||
|
|
751d683b3e |
@@ -12,8 +12,11 @@ add_definitions(-DBELL_USE_MBEDTLS)
|
|||||||
add_definitions(-Wno-unused-variable -Wno-unused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
|
add_definitions(-Wno-unused-variable -Wno-unused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation)
|
||||||
|
|
||||||
set(BELL_DISABLE_CODECS ON)
|
set(BELL_DISABLE_CODECS ON)
|
||||||
set(BELL_EXTERNAL_TREMOR "idf::codecs")
|
set(BELL_DISABLE_SINKS ON)
|
||||||
set(BELL_EXTERNAL_CJSON "idf::json")
|
set(CSPOT_TARGET_ESP32 ON)
|
||||||
|
# becase CMake is so broken, the cache set below overrides a normal "set" for the first build
|
||||||
|
set(BELL_EXTERNAL_TREMOR "idf::codecs" CACHE STRING "provide own codecs")
|
||||||
|
set(BELL_EXTERNAL_CJSON "idf::json" CACHE STRING "provide own CJSON")
|
||||||
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cspot ${CMAKE_CURRENT_BINARY_DIR}/cspot)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cspot ${CMAKE_CURRENT_BINARY_DIR}/cspot)
|
||||||
target_link_libraries(${COMPONENT_LIB} PRIVATE cspot ${EXTRA_REQ_LIBS})
|
target_link_libraries(${COMPONENT_LIB} PRIVATE cspot ${EXTRA_REQ_LIBS})
|
||||||
|
|||||||
@@ -25,26 +25,22 @@ if(UNIX AND NOT APPLE)
|
|||||||
# TODO: migrate from this to native linux mDNS
|
# TODO: migrate from this to native linux mDNS
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (GENERATE_PROTOS)
|
# Build protobuf code
|
||||||
file(GLOB SOURCES "src/*.cpp" "src/*.c")
|
#set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
set(NANOPB_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}")
|
#file(GLOB PROTOS protobuf/*.proto)
|
||||||
set(PROTOS protobuf/authentication.proto protobuf/mercury.proto protobuf/keyexchange.proto protobuf/spirc.proto protobuf/metadata.proto)
|
#nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS})
|
||||||
message(${PROTOS})
|
#add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
|
||||||
message("building protobuf")
|
#set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS}
|
||||||
message(${CMAKE_CURRENT_SOURCE_DIR})
|
# PROPERTIES GENERATED TRUE)
|
||||||
nanopb_generate_cpp(PROTO_SRCS PROTO_HDRS RELPATH ${CMAKE_CURRENT_SOURCE_DIR} ${PROTOS})
|
|
||||||
add_custom_target(generate_proto_sources DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
|
file(GLOB SOURCES "src/*.cpp" "src/*.c" "protobuf/*.c")
|
||||||
set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES GENERATED TRUE)
|
message("BEWARE => NOT GENERATING PROTOBUF")
|
||||||
set(GENERATED_INCLUDES ${CMAKE_CURRENT_BINARY_DIR})
|
set(GENERATED_INCLUDES ".")
|
||||||
else()
|
|
||||||
file(GLOB SOURCES "src/*.cpp" "src/*.c" "protobuf/*.c")
|
|
||||||
message("BEWARE => NOT GENERATING PROTOBUF")
|
|
||||||
set(GENERATED_INCLUDES ".")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS})
|
add_library(cspot STATIC ${SOURCES} ${PROTO_SRCS})
|
||||||
# PUBLIC to propagate includes from bell to cspot dependents
|
# PUBLIC to propagate includes from bell to cspot dependents
|
||||||
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
|
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
|
||||||
target_compile_definitions(bell PUBLIC PB_FIELD_32BIT)
|
target_compile_definitions(bell PUBLIC PB_FIELD_32BIT)
|
||||||
target_link_libraries(cspot PUBLIC ${EXTRA_LIBS})
|
target_link_libraries(cspot PUBLIC ${EXTRA_LIBS})
|
||||||
|
#target_include_directories(cspot PUBLIC "include" ${CMAKE_CURRENT_BINARY_DIR} ${NANOPB_INCLUDE_DIRS})
|
||||||
target_include_directories(cspot PUBLIC "include" ${GENERATED_INCLUDES} ${NANOPB_INCLUDE_DIRS})
|
target_include_directories(cspot PUBLIC "include" ${GENERATED_INCLUDES} ${NANOPB_INCLUDE_DIRS})
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
cmake_policy(SET CMP0077 NEW)
|
||||||
|
|
||||||
project(bell)
|
project(bell)
|
||||||
|
|
||||||
# Configurable options
|
# Configurable options
|
||||||
option(BELL_DISABLE_CODECS "Disable libhelix AAC and MP3 codecs" OFF)
|
option(BELL_DISABLE_CODECS "Disable libhelix AAC and MP3 codecs" OFF)
|
||||||
#set(BELL_EXTERNAL_CJSON "" CACHE STRING "External cJSON library target name, optional")
|
option(BELL_DISABLE_SINKS "Disable built-in audio sink implementations" OFF)
|
||||||
#set(BELL_EXTERNAL_TREMOR "" CACHE STRING "External tremor library target name, optional")
|
option(BELL_USE_ALSA "Enable ALSA sink" OFF)
|
||||||
|
option(BELL_USE_PORTAUDIO "Enable PortAudio sink" OFF)
|
||||||
|
set(BELL_EXTERNAL_CJSON "" CACHE STRING "External cJSON library target name, optional")
|
||||||
|
set(BELL_EXTERNAL_TREMOR "" CACHE STRING "External tremor library target name, optional")
|
||||||
|
|
||||||
# Include nanoPB library
|
# Include nanoPB library
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra)
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/nanopb/extra)
|
||||||
find_package(Nanopb REQUIRED)
|
find_package(Nanopb REQUIRED)
|
||||||
include_directories(${NANOPB_INCLUDE_DIRS})
|
list(APPEND EXTRA_INCLUDES ${NANOPB_INCLUDE_DIRS})
|
||||||
|
|
||||||
# CMake options
|
# CMake options
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
add_definitions(-DUSE_DEFAULT_STDLIB=1)
|
add_definitions(-DUSE_DEFAULT_STDLIB=1)
|
||||||
|
|
||||||
# Main library sources
|
# Main library sources
|
||||||
@@ -74,6 +79,33 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT BELL_DISABLE_SINKS)
|
||||||
|
set(PLATFORM "unix")
|
||||||
|
if(ESP_PLATFORM)
|
||||||
|
set(PLATFORM "esp")
|
||||||
|
endif()
|
||||||
|
# Add all built-in audio sinks
|
||||||
|
file(GLOB SINK_SOURCES "src/sinks/${PLATFORM}/*.cpp" "src/sinks/${PLATFORM}/*.c")
|
||||||
|
# Find ALSA if required, else remove the sink
|
||||||
|
if(BELL_USE_ALSA)
|
||||||
|
find_package(ALSA REQUIRED)
|
||||||
|
list(APPEND EXTRA_INCLUDES ${ALSA_INCLUDE_DIRS})
|
||||||
|
list(APPEND EXTRA_LIBS ${ALSA_LIBRARIES})
|
||||||
|
else()
|
||||||
|
list(REMOVE_ITEM SINK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/sinks/unix/ALSAAudioSink.cpp)
|
||||||
|
endif()
|
||||||
|
# Find PortAudio if required, else remove the sink
|
||||||
|
if(BELL_USE_PORTAUDIO)
|
||||||
|
find_package(portaudio REQUIRED)
|
||||||
|
list(APPEND EXTRA_INCLUDES ${PORTAUDIO_INCLUDE_DIRS})
|
||||||
|
list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES})
|
||||||
|
else()
|
||||||
|
list(REMOVE_ITEM SINK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/sinks/unix/PortAudioSink.cpp)
|
||||||
|
endif()
|
||||||
|
list(APPEND SOURCES ${SINK_SOURCES})
|
||||||
|
list(APPEND EXTRA_INCLUDES "include/sinks/${PLATFORM}")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BELL_EXTERNAL_CJSON)
|
if(BELL_EXTERNAL_CJSON)
|
||||||
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
|
list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
|
||||||
else()
|
else()
|
||||||
@@ -91,9 +123,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(bell STATIC ${SOURCES})
|
add_library(bell STATIC ${SOURCES})
|
||||||
|
|
||||||
message(${NANOPB_INCLUDE_DIRS})
|
|
||||||
# PUBLIC to propagate esp-idf includes to bell dependents
|
# PUBLIC to propagate esp-idf includes to bell dependents
|
||||||
target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
|
target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
|
||||||
target_include_directories(bell PUBLIC "include" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(bell PUBLIC "include" "include/platform" ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
|
target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC)
|
||||||
|
|||||||
@@ -80,9 +80,8 @@ void bell::HTTPServer::listen() {
|
|||||||
socket(server->ai_family, server->ai_socktype, server->ai_protocol);
|
socket(server->ai_family, server->ai_socktype, server->ai_protocol);
|
||||||
struct sockaddr_in clientname;
|
struct sockaddr_in clientname;
|
||||||
socklen_t incomingSockSize;
|
socklen_t incomingSockSize;
|
||||||
int i;
|
|
||||||
int yes = true;
|
int yes = true;
|
||||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
|
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*) &yes, sizeof(int)) < 0) {
|
||||||
throw std::runtime_error("setsockopt failed: " +
|
throw std::runtime_error("setsockopt failed: " +
|
||||||
std::string(strerror(errno)));
|
std::string(strerror(errno)));
|
||||||
}
|
}
|
||||||
@@ -100,62 +99,65 @@ void bell::HTTPServer::listen() {
|
|||||||
FD_ZERO(&activeFdSet);
|
FD_ZERO(&activeFdSet);
|
||||||
FD_SET(sockfd, &activeFdSet);
|
FD_SET(sockfd, &activeFdSet);
|
||||||
|
|
||||||
for (;;) {
|
for (int maxfd = sockfd;;) {
|
||||||
/* Block until input arrives on one or more active sockets. */
|
/* Block until input arrives on one or more active sockets. */
|
||||||
readFdSet = activeFdSet;
|
readFdSet = activeFdSet;
|
||||||
struct timeval tv = {0, 100000};
|
struct timeval tv = {0, 100000};
|
||||||
|
|
||||||
if (select(FD_SETSIZE, &readFdSet, NULL, NULL, &tv) < 0) {
|
if (select(maxfd + 1, &readFdSet, NULL, NULL, &tv) < 0) {
|
||||||
BELL_LOG(error, "http", "Error in select");
|
BELL_LOG(error, "http", "Error in select");
|
||||||
perror("select");
|
perror("select");
|
||||||
// exit(EXIT_FAILURE);
|
// exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Service all the sockets with input pending. */
|
/* Service listening socket. */
|
||||||
for (i = 0; i < FD_SETSIZE; ++i)
|
if (FD_ISSET(sockfd, &readFdSet)) {
|
||||||
if (FD_ISSET(i, &readFdSet)) {
|
int newFd;
|
||||||
if (i == sockfd) {
|
incomingSockSize = sizeof(clientname);
|
||||||
/* Connection request on original socket. */
|
newFd = accept(sockfd, (struct sockaddr*)&clientname,
|
||||||
int newFd;
|
&incomingSockSize);
|
||||||
incomingSockSize = sizeof(clientname);
|
if (newFd < 0) {
|
||||||
newFd = accept(sockfd, (struct sockaddr *)&clientname,
|
perror("accept");
|
||||||
&incomingSockSize);
|
exit(EXIT_FAILURE);
|
||||||
if (newFd < 0) {
|
}
|
||||||
perror("accept");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_SET(newFd, &activeFdSet);
|
FD_SET(newFd, &activeFdSet);
|
||||||
|
|
||||||
HTTPConnection conn = {.buffer = std::vector<uint8_t>(128),
|
HTTPConnection conn = { .buffer = std::vector<uint8_t>(128),
|
||||||
.httpMethod = ""};
|
.httpMethod = "" };
|
||||||
|
|
||||||
this->connections.insert({newFd, conn});
|
this->connections.insert({ newFd, conn });
|
||||||
} else {
|
}
|
||||||
/* Data arriving on an already-connected socket. */
|
|
||||||
readFromClient(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Service other sockets and update set & max */
|
||||||
|
maxfd = sockfd;
|
||||||
for (auto it = this->connections.cbegin();
|
for (auto it = this->connections.cbegin();
|
||||||
it != this->connections.cend() /* not hoisted */;
|
it != this->connections.cend() /* not hoisted */;
|
||||||
/* no increment */) {
|
/* no increment */) {
|
||||||
|
int fd = (*it).first;
|
||||||
if ((*it).second.toBeClosed) {
|
if ((*it).second.toBeClosed) {
|
||||||
close((*it).first);
|
close(fd);
|
||||||
FD_CLR((*it).first, &activeFdSet);
|
FD_CLR(fd, &activeFdSet);
|
||||||
this->connections.erase(
|
this->connections.erase(
|
||||||
it++); // or "it = m.erase(it)" since C++11
|
it++); // or "it = m.erase(it)" since C++11
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
if (fd != sockfd && FD_ISSET(fd, &readFdSet)) {
|
||||||
|
/* Data arriving on an already-connected socket. */
|
||||||
|
readFromClient(fd);
|
||||||
|
}
|
||||||
|
if (fd > maxfd) maxfd = fd;
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bell::HTTPServer::readFromClient(int clientFd) {
|
void bell::HTTPServer::readFromClient(int clientFd) {
|
||||||
HTTPConnection &conn = this->connections[clientFd];
|
HTTPConnection &conn = this->connections[clientFd];
|
||||||
|
|
||||||
int nbytes = recv(clientFd, &conn.buffer[0], conn.buffer.size(), 0);
|
int nbytes = recv(clientFd, (char*) &conn.buffer[0], conn.buffer.size(), 0);
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
BELL_LOG(error, "http", "Error reading from client");
|
BELL_LOG(error, "http", "Error reading from client");
|
||||||
perror("recv");
|
perror("recv");
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ std::vector<uint8_t> PlainConnection::readBlock(size_t size)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (retries++ > 4) throw std::runtime_error("Error in read");
|
if (retries++ > 4) throw std::runtime_error("Error in read");
|
||||||
|
goto READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx += n;
|
idx += n;
|
||||||
|
|||||||
@@ -110,8 +110,7 @@ void ws2812_control_init(void)
|
|||||||
|
|
||||||
void ws2812_write_leds(struct led_state new_state) {
|
void ws2812_write_leds(struct led_state new_state) {
|
||||||
setup_rmt_data_buffer(new_state);
|
setup_rmt_data_buffer(new_state);
|
||||||
ESP_ERROR_CHECK(rmt_write_items(LED_RMT_TX_CHANNEL, led_data_buffer, LED_BUFFER_ITEMS, false));
|
rmt_write_items(LED_RMT_TX_CHANNEL, led_data_buffer, LED_BUFFER_ITEMS, false);
|
||||||
ESP_ERROR_CHECK(rmt_wait_tx_done(LED_RMT_TX_CHANNEL, portMAX_DELAY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_rmt_data_buffer(struct led_state new_state)
|
void setup_rmt_data_buffer(struct led_state new_state)
|
||||||
|
|||||||
@@ -822,7 +822,7 @@ static state_machine_result_t WIFI_CONNECTING_STATE_handler(state_machine_t* con
|
|||||||
network_connect_active_ssid(State_Machine);
|
network_connect_active_ssid(State_Machine);
|
||||||
break;
|
break;
|
||||||
case EN_LOST_CONNECTION:
|
case EN_LOST_CONNECTION:
|
||||||
if(nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) {
|
if(nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE || nm->event_parameters->disconnected_event->reason == WIFI_REASON_AUTH_EXPIRE || nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_EXPIRE) {
|
||||||
ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect.");
|
ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect.");
|
||||||
}
|
}
|
||||||
else if(nm->event_parameters->disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) {
|
else if(nm->event_parameters->disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) {
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ sub initFirmwareDownload {
|
|||||||
$cb->() if $cb;
|
$cb->() if $cb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elsif ($cb) {
|
||||||
|
$cb->();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
sub {
|
sub {
|
||||||
my ($http, $error) = @_;
|
my ($http, $error) = @_;
|
||||||
@@ -119,10 +122,15 @@ sub prefetchFirmware {
|
|||||||
|
|
||||||
$cb->($releaseInfo, _gh2lmsUrl($url), $customFwUrl) if $cb;
|
$cb->($releaseInfo, _gh2lmsUrl($url), $customFwUrl) if $cb;
|
||||||
}
|
}
|
||||||
|
elsif ($cb) {
|
||||||
|
$cb->();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
sub {
|
sub {
|
||||||
my ($http, $error) = @_;
|
my ($http, $error) = @_;
|
||||||
$log->error("Failed to get releases from Github: $error");
|
$log->error("Failed to get releases from Github: $error");
|
||||||
|
|
||||||
|
$cb->() if $cb;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout => 10,
|
timeout => 10,
|
||||||
|
|||||||
@@ -1,3 +1,55 @@
|
|||||||
|
[% IF useExtJS; extJsScripts = BLOCK %]
|
||||||
|
<script type="text/javascript">
|
||||||
|
Ext.onReady(function () {
|
||||||
|
new Ext.util.TaskRunner().start({
|
||||||
|
run: checkEq,
|
||||||
|
interval: 1000
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkEq() {
|
||||||
|
var eqValues = [];
|
||||||
|
this.lastValues = this.lastValues || [];
|
||||||
|
|
||||||
|
for (var x = 0; x < 10; x++) {
|
||||||
|
eqValues[x] = Ext.get('pref_equalizer.' + x).dom.value || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eqValues.join() != this.lastValues.join()) {
|
||||||
|
this.lastValues = eqValues;
|
||||||
|
SqueezeJS.Controller.request({
|
||||||
|
params: ['[% playerid %]', ['squeezeesp32', 'seteq', eqValues.join()]]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
[% END; ELSIF !useExtJS; pageHeaderScripts = BLOCK %]
|
||||||
|
<script type="text/javascript">
|
||||||
|
setInterval(checkEq, 1000);
|
||||||
|
|
||||||
|
function checkEq() {
|
||||||
|
var eqValues = [];
|
||||||
|
this.lastValues = this.lastValues || [];
|
||||||
|
|
||||||
|
for (var x = 0; x < 10; x++) {
|
||||||
|
eqValues[x] = $('pref_equalizer.' + x).value || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eqValues.join() != this.lastValues.join()) {
|
||||||
|
this.lastValues = eqValues;
|
||||||
|
new Ajax.Request('/jsonrpc.js', {
|
||||||
|
method: 'post',
|
||||||
|
postBody: JSON.stringify({
|
||||||
|
id: 1,
|
||||||
|
method: 'slim.request',
|
||||||
|
params: ['[% playerid %]', ['squeezeesp32', 'seteq', eqValues.join()]]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
[% END; END %]
|
||||||
|
|
||||||
[% PROCESS settings/header.html %]
|
[% PROCESS settings/header.html %]
|
||||||
|
|
||||||
[% WRAPPER setting title="PLUGIN_SQUEEZEESP32_FIRMWARE" desc="" %]
|
[% WRAPPER setting title="PLUGIN_SQUEEZEESP32_FIRMWARE" desc="" %]
|
||||||
@@ -59,62 +111,36 @@
|
|||||||
<div>[% "PLUGIN_SQUEEZEESP32_EQUALIZER_SAVE" | string %]</div>
|
<div>[% "PLUGIN_SQUEEZEESP32_EQUALIZER_SAVE" | string %]</div>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
<script TYPE="text/javascript">
|
|
||||||
if (Ext) {
|
|
||||||
Ext.onReady(function () {
|
|
||||||
new Ext.util.TaskRunner().start({
|
|
||||||
run: checkEq,
|
|
||||||
interval: 1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function checkEq() {
|
|
||||||
var eqValues = [];
|
|
||||||
this.lastValues = this.lastValues || [];
|
|
||||||
|
|
||||||
for (var x = 0; x < 10; x++) {
|
|
||||||
eqValues[x] = Ext.get('pref_equalizer.' + x).dom.value || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eqValues.join() != this.lastValues.join()) {
|
|
||||||
this.lastValues = eqValues;
|
|
||||||
SqueezeJS.Controller.request({
|
|
||||||
params: ['[% playerid %]', ['squeezeesp32', 'seteq', eqValues.join()]]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
[% WRAPPER settingSection %]
|
[% WRAPPER settingSection %]
|
||||||
[% WRAPPER settingGroup title='31Hz' desc="" %]
|
[% WRAPPER settingGroup title='31Hz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.0" id="pref_equalizer.0" value="[% pref_equalizer.0 %]" size="2"">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.0" id="pref_equalizer.0" value="[% pref_equalizer.0 || 0 %]" size="2"">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='62Hz' desc="" %]
|
[% WRAPPER settingGroup title='62Hz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.1" id="pref_equalizer.1" value="[% pref_equalizer.1 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.1" id="pref_equalizer.1" value="[% pref_equalizer.1 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='125Hz' desc="" %]
|
[% WRAPPER settingGroup title='125Hz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.2" id="pref_equalizer.2" value="[% pref_equalizer.2 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.2" id="pref_equalizer.2" value="[% pref_equalizer.2 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='250Hz' desc="" %]
|
[% WRAPPER settingGroup title='250Hz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.3" id="pref_equalizer.3" value="[% pref_equalizer.3 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.3" id="pref_equalizer.3" value="[% pref_equalizer.3 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='500Hz' desc="" %]
|
[% WRAPPER settingGroup title='500Hz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.4" id="pref_equalizer.4" value="[% pref_equalizer.4 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.4" id="pref_equalizer.4" value="[% pref_equalizer.4 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='1kHz' desc="" %]
|
[% WRAPPER settingGroup title='1kHz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.5" id="pref_equalizer.5" value="[% pref_equalizer.5 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.5" id="pref_equalizer.5" value="[% pref_equalizer.5 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='2kHz' desc="" %]
|
[% WRAPPER settingGroup title='2kHz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.6" id="pref_equalizer.6" value="[% pref_equalizer.6 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.6" id="pref_equalizer.6" value="[% pref_equalizer.6 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='4kHz' desc="" %]
|
[% WRAPPER settingGroup title='4kHz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.7" id="pref_equalizer.7" value="[% pref_equalizer.7 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.7" id="pref_equalizer.7" value="[% pref_equalizer.7 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='8kHz' desc="" %]
|
[% WRAPPER settingGroup title='8kHz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.8" id="pref_equalizer.8" value="[% pref_equalizer.8 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.8" id="pref_equalizer.8" value="[% pref_equalizer.8 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% WRAPPER settingGroup title='16kHz' desc="" %]
|
[% WRAPPER settingGroup title='16kHz' desc="" %]
|
||||||
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.9" id="pref_equalizer.9" value="[% pref_equalizer.9 %]" size="2">
|
<input type="text" class="stdedit sliderInput_-13_20" name="pref_equalizer.9" id="pref_equalizer.9" value="[% pref_equalizer.9 || 0 %]" size="2">
|
||||||
[% END %]
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ our $defaultPrefs = {
|
|||||||
'analogOutMode' => 0,
|
'analogOutMode' => 0,
|
||||||
'bass' => 0,
|
'bass' => 0,
|
||||||
'treble' => 0,
|
'treble' => 0,
|
||||||
'lineInAlwaysOn' => 0,
|
'lineInAlwaysOn' => 0,
|
||||||
'lineInLevel' => 50,
|
'lineInLevel' => 50,
|
||||||
'menuItem' => [qw(
|
'menuItem' => [qw(
|
||||||
NOW_PLAYING
|
NOW_PLAYING
|
||||||
BROWSE_MUSIC
|
BROWSE_MUSIC
|
||||||
@@ -67,51 +67,66 @@ sub minBass { -13 }
|
|||||||
sub init {
|
sub init {
|
||||||
my $client = shift;
|
my $client = shift;
|
||||||
my ($id, $caps) = @_;
|
my ($id, $caps) = @_;
|
||||||
|
|
||||||
my ($depth) = $caps =~ /Depth=(\d+)/;
|
my ($depth) = $caps =~ /Depth=(\d+)/;
|
||||||
$client->depth($depth || 16);
|
$client->depth($depth || 16);
|
||||||
|
|
||||||
if (!$handlersAdded) {
|
if (!$handlersAdded) {
|
||||||
|
|
||||||
# Add a handler for line-in/out status changes
|
# Add a handler for line-in/out status changes
|
||||||
Slim::Networking::Slimproto::addHandler( LIOS => \&lineInOutStatus );
|
Slim::Networking::Slimproto::addHandler( LIOS => \&lineInOutStatus );
|
||||||
|
|
||||||
# Create a new event for sending LIOS updates
|
# Create a new event for sending LIOS updates
|
||||||
Slim::Control::Request::addDispatch(
|
Slim::Control::Request::addDispatch(
|
||||||
['lios', '_state'],
|
['lios', '_state'],
|
||||||
[1, 0, 0, undef],
|
[1, 0, 0, undef],
|
||||||
);
|
);
|
||||||
|
|
||||||
Slim::Control::Request::addDispatch(
|
Slim::Control::Request::addDispatch(
|
||||||
['lios', 'linein', '_state'],
|
['lios', 'linein', '_state'],
|
||||||
[1, 0, 0, undef],
|
[1, 0, 0, undef],
|
||||||
);
|
);
|
||||||
|
|
||||||
Slim::Control::Request::addDispatch(
|
Slim::Control::Request::addDispatch(
|
||||||
['lios', 'lineout', '_state'],
|
['lios', 'lineout', '_state'],
|
||||||
[1, 0, 0, undef],
|
[1, 0, 0, undef],
|
||||||
);
|
);
|
||||||
|
|
||||||
$handlersAdded = 1;
|
$handlersAdded = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$client->SUPER::init(@_);
|
$client->SUPER::init(@_);
|
||||||
Plugins::SqueezeESP32::FirmwareHelper::init($client);
|
Plugins::SqueezeESP32::FirmwareHelper::init($client);
|
||||||
|
|
||||||
main::INFOLOG && $log->is_info && $log->info("SqueezeESP player connected: " . $client->id);
|
main::INFOLOG && $log->is_info && $log->info("SqueezeESP player connected: " . $client->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub initPrefs {
|
sub initPrefs {
|
||||||
my $client = shift;
|
my $client = shift;
|
||||||
|
|
||||||
$sprefs->client($client)->init($defaultPrefs);
|
$sprefs->client($client)->init($defaultPrefs);
|
||||||
|
|
||||||
$prefs->client($client)->init( {
|
$prefs->client($client)->init( {
|
||||||
equalizer => [(0) x 10],
|
equalizer => [(0) x 10],
|
||||||
artwork => undef,
|
artwork => undef,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
$prefs->setValidate({
|
||||||
|
validator => sub {
|
||||||
|
my ($pref, $new, $params, $old, $client) = @_;
|
||||||
|
|
||||||
|
$new ||= [(0) x 10];
|
||||||
|
|
||||||
|
foreach (0..9) {
|
||||||
|
return 0 if $new->[$_] < $client->minBass;
|
||||||
|
return 0 if $new->[$_] > $client->maxBass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}, 'equalizer');
|
||||||
|
|
||||||
$client->SUPER::initPrefs;
|
$client->SUPER::initPrefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,15 +136,15 @@ sub power {
|
|||||||
|
|
||||||
my $res = $client->SUPER::power($on, @_);
|
my $res = $client->SUPER::power($on, @_);
|
||||||
return $res unless defined $on;
|
return $res unless defined $on;
|
||||||
|
|
||||||
if ($on) {
|
if ($on) {
|
||||||
$client->update_artwork(1);
|
$client->update_artwork(1);
|
||||||
} else {
|
} else {
|
||||||
$client->clear_artwork(1);
|
$client->clear_artwork(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Allow the player to define it's display width (and probably more)
|
# Allow the player to define it's display width (and probably more)
|
||||||
sub playerSettingsFrame {
|
sub playerSettingsFrame {
|
||||||
@@ -162,16 +177,16 @@ sub playerSettingsFrame {
|
|||||||
sub bass {
|
sub bass {
|
||||||
my ($client, $new) = @_;
|
my ($client, $new) = @_;
|
||||||
my $value = $client->SUPER::bass($new);
|
my $value = $client->SUPER::bass($new);
|
||||||
|
|
||||||
$client->update_equalizer($value, [2, 1, 3]) if defined $new;
|
$client->update_equalizer($value, [2, 1, 3]) if defined $new;
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub treble {
|
sub treble {
|
||||||
my ($client, $new) = @_;
|
my ($client, $new) = @_;
|
||||||
my $value = $client->SUPER::treble($new);
|
my $value = $client->SUPER::treble($new);
|
||||||
|
|
||||||
$client->update_equalizer($value, [8, 9, 7]) if defined $new;
|
$client->update_equalizer($value, [8, 9, 7]) if defined $new;
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
@@ -189,8 +204,8 @@ sub send_equalizer {
|
|||||||
sub update_equalizer {
|
sub update_equalizer {
|
||||||
my ($client, $value, $index) = @_;
|
my ($client, $value, $index) = @_;
|
||||||
return if $client->tone_update;
|
return if $client->tone_update;
|
||||||
|
|
||||||
my $equalizer = $prefs->client($client)->get('equalizer');
|
my $equalizer = $prefs->client($client)->get('equalizer');
|
||||||
$equalizer->[$index->[0]] = $value;
|
$equalizer->[$index->[0]] = $value;
|
||||||
$equalizer->[$index->[1]] = int($value / 2 + 0.5);
|
$equalizer->[$index->[1]] = int($value / 2 + 0.5);
|
||||||
$equalizer->[$index->[2]] = int($value / 4 + 0.5);
|
$equalizer->[$index->[2]] = int($value / 4 + 0.5);
|
||||||
@@ -203,7 +218,7 @@ sub update_tones {
|
|||||||
$client->tone_update(1);
|
$client->tone_update(1);
|
||||||
$sprefs->client($client)->set('bass', int(($equalizer->[1] * 2 + $equalizer->[2] + $equalizer->[3] * 4) / 7 + 0.5));
|
$sprefs->client($client)->set('bass', int(($equalizer->[1] * 2 + $equalizer->[2] + $equalizer->[3] * 4) / 7 + 0.5));
|
||||||
$sprefs->client($client)->set('treble', int(($equalizer->[7] * 4 + $equalizer->[8] + $equalizer->[9] * 2) / 7 + 0.5));
|
$sprefs->client($client)->set('treble', int(($equalizer->[7] * 4 + $equalizer->[8] + $equalizer->[9] * 2) / 7 + 0.5));
|
||||||
$client->tone_update(0);
|
$client->tone_update(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub update_artwork {
|
sub update_artwork {
|
||||||
@@ -212,7 +227,7 @@ sub update_artwork {
|
|||||||
|
|
||||||
my $artwork = $cprefs->get('artwork') || return;
|
my $artwork = $cprefs->get('artwork') || return;
|
||||||
return unless $artwork->{'enable'} && $client->display->isa("Plugins::SqueezeESP32::Graphics");
|
return unless $artwork->{'enable'} && $client->display->isa("Plugins::SqueezeESP32::Graphics");
|
||||||
|
|
||||||
my $header = pack('Nnn', $artwork->{'enable'}, $artwork->{'x'}, $artwork->{'y'});
|
my $header = pack('Nnn', $artwork->{'enable'}, $artwork->{'x'}, $artwork->{'y'});
|
||||||
$client->sendFrame( grfa => \$header );
|
$client->sendFrame( grfa => \$header );
|
||||||
$client->display->update;
|
$client->display->update;
|
||||||
@@ -267,7 +282,7 @@ sub clear_artwork {
|
|||||||
if ((!$artwork->{'x'} && !$artwork->{'y'}) || $force) {
|
if ((!$artwork->{'x'} && !$artwork->{'y'}) || $force) {
|
||||||
$client->sendFrame(grfa => \("\x00"x4));
|
$client->sendFrame(grfa => \("\x00"x4));
|
||||||
$client->display->update;
|
$client->display->update;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +299,7 @@ sub config_artwork {
|
|||||||
sub reconnect {
|
sub reconnect {
|
||||||
my $client = shift;
|
my $client = shift;
|
||||||
$client->SUPER::reconnect(@_);
|
$client->SUPER::reconnect(@_);
|
||||||
|
|
||||||
$client->pluginData('artwork_md5', '');
|
$client->pluginData('artwork_md5', '');
|
||||||
$client->config_artwork if $client->display->isa("Plugins::SqueezeESP32::Graphics");
|
$client->config_artwork if $client->display->isa("Plugins::SqueezeESP32::Graphics");
|
||||||
$client->send_equalizer;
|
$client->send_equalizer;
|
||||||
@@ -323,18 +338,18 @@ sub lineOutConnected {
|
|||||||
|
|
||||||
sub lineInOutStatus {
|
sub lineInOutStatus {
|
||||||
my ( $client, $data_ref ) = @_;
|
my ( $client, $data_ref ) = @_;
|
||||||
|
|
||||||
my $state = unpack 'n', $$data_ref;
|
my $state = unpack 'n', $$data_ref;
|
||||||
|
|
||||||
my $oldState = {
|
my $oldState = {
|
||||||
in => $client->lineInConnected(),
|
in => $client->lineInConnected(),
|
||||||
out => $client->lineOutConnected(),
|
out => $client->lineOutConnected(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Slim::Networking::Slimproto::voltage( $client, $state );
|
Slim::Networking::Slimproto::voltage( $client, $state );
|
||||||
|
|
||||||
Slim::Control::Request::notifyFromArray( $client, [ 'lios', $state ] );
|
Slim::Control::Request::notifyFromArray( $client, [ 'lios', $state ] );
|
||||||
|
|
||||||
if ($oldState->{in} != $client->lineInConnected()) {
|
if ($oldState->{in} != $client->lineInConnected()) {
|
||||||
Slim::Control::Request::notifyFromArray( $client, [ 'lios', 'linein', $client->lineInConnected() ] );
|
Slim::Control::Request::notifyFromArray( $client, [ 'lios', 'linein', $client->lineInConnected() ] );
|
||||||
if ( Slim::Utils::PluginManager->isEnabled('Slim::Plugin::LineIn::Plugin')) {
|
if ( Slim::Utils::PluginManager->isEnabled('Slim::Plugin::LineIn::Plugin')) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package Plugins::SqueezeESP32::PlayerSettings;
|
|||||||
use strict;
|
use strict;
|
||||||
use base qw(Slim::Web::Settings);
|
use base qw(Slim::Web::Settings);
|
||||||
use JSON::XS::VersionOneAndTwo;
|
use JSON::XS::VersionOneAndTwo;
|
||||||
use List::Util qw(first);
|
use List::Util qw(first min max);
|
||||||
|
|
||||||
use Slim::Utils::Log;
|
use Slim::Utils::Log;
|
||||||
use Slim::Utils::Prefs;
|
use Slim::Utils::Prefs;
|
||||||
@@ -79,9 +79,10 @@ sub handler {
|
|||||||
|
|
||||||
if ($client->can('depth') && $client->depth == 16) {
|
if ($client->can('depth') && $client->depth == 16) {
|
||||||
my $equalizer = $cprefs->get('equalizer');
|
my $equalizer = $cprefs->get('equalizer');
|
||||||
for my $i (0 .. $#{$equalizer}) {
|
foreach (0 .. 9) {
|
||||||
$equalizer->[$i] = $paramRef->{"pref_equalizer.$i"} || 0;
|
$equalizer->[$_] = min($client->maxBass, max($client->minBass, $paramRef->{"pref_equalizer.$_"} || 0))
|
||||||
}
|
}
|
||||||
|
$equalizer = [ splice(@$equalizer, 0, 10) ];
|
||||||
$cprefs->set('equalizer', $equalizer);
|
$cprefs->set('equalizer', $equalizer);
|
||||||
$client->update_tones($equalizer);
|
$client->update_tones($equalizer);
|
||||||
}
|
}
|
||||||
@@ -97,6 +98,7 @@ sub handler {
|
|||||||
$paramRef->{'pref_equalizer'} = $cprefs->get('equalizer') if $client->can('depth') && $client->depth == 16;
|
$paramRef->{'pref_equalizer'} = $cprefs->get('equalizer') if $client->can('depth') && $client->depth == 16;
|
||||||
$paramRef->{'player_ip'} = $client->ip;
|
$paramRef->{'player_ip'} = $client->ip;
|
||||||
|
|
||||||
|
require Plugins::SqueezeESP32::FirmwareHelper;
|
||||||
Plugins::SqueezeESP32::FirmwareHelper::initFirmwareDownload($client, sub {
|
Plugins::SqueezeESP32::FirmwareHelper::initFirmwareDownload($client, sub {
|
||||||
my ($currentFWInfo, $newFWUrl, $customFwUrl) = @_;
|
my ($currentFWInfo, $newFWUrl, $customFwUrl) = @_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user