Reposition audio config and other small fixes - release

This commit is contained in:
Sebastien
2020-10-09 16:35:30 -04:00
parent b301376fc6
commit 3e74292fc0
9 changed files with 136 additions and 45 deletions

View File

@@ -22,6 +22,7 @@
const char * desc_squeezelite ="Squeezelite Options";
const char * desc_dac= "DAC Options";
const char * desc_spdif= "SPDIF Options";
const char * desc_audio= "General Audio Options";
#define CODECS_BASE "flac,pcm,mp3,ogg"
@@ -69,6 +70,10 @@ static struct {
struct arg_lit *clear;
struct arg_end *end;
} spdif_args;
static struct {
struct arg_str *jack_behavior;
struct arg_end *end;
} audio_args;
static struct {
struct arg_str * server; // -s <server>[:<port>]\tConnect to specified server, otherwise uses autodiscovery to find server\n"
struct arg_str * buffers;// " -b <stream>:<output>\tSpecify internal Stream and Output buffer sizes in Kbytes\n"
@@ -137,8 +142,53 @@ int check_missing_parm(struct arg_int * int_parm, FILE * f){
}
return res;
}
static int do_audio_cmd(int argc, char **argv){
esp_err_t err=ESP_OK;
int nerrors = arg_parse(argc, argv,(void **)&audio_args);
char *buf = NULL;
size_t buf_size = 0;
FILE *f = open_memstream(&buf, &buf_size);
if (f == NULL) {
cmd_send_messaging(argv[0],MESSAGING_ERROR,"Unable to open memory stream.\n");
return 1;
}
if(nerrors >0){
arg_print_errors(f,audio_args.end,desc_audio);
return 1;
}
if(audio_args.jack_behavior->count>0){
err = ESP_OK; // suppress any error code that might have happened in a previous step
if(strcasecmp(audio_args.jack_behavior->sval[0],"Headphones")){
err = config_set_value(NVS_TYPE_STR, "jack_mutes_amp", "y");
}
else if(strcasecmp(audio_args.jack_behavior->sval[0],"Subwoofer")){
err = config_set_value(NVS_TYPE_STR, "jack_mutes_amp", "n");
}
else {
nerrors++;
fprintf(f,"Unknown Audio Jack Behavior %s.\n",audio_args.jack_behavior->sval[0]);
}
if(err!=ESP_OK){
nerrors++;
fprintf(f,"Error setting Audio Jack Behavior %s. %s\n",audio_args.jack_behavior->sval[0], esp_err_to_name(err));
}
else {
fprintf(f,"Audio Jack Behavior changed to %s\n",audio_args.jack_behavior->sval[0]);
}
}
if(!nerrors ){
fprintf(f,"Done.\n");
}
fflush (f);
cmd_send_messaging(argv[0],nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
fclose(f);
FREE_AND_NULL(buf);
return (nerrors==0 && err==ESP_OK)?0:1;
}
static int do_spdif_cmd(int argc, char **argv){
i2s_platform_config_t i2s_dac_pin = {
.i2c_addr = -1,
@@ -329,6 +379,15 @@ cJSON * spdif_cb(){
return values;
}
cJSON * audio_cb(){
cJSON * values = cJSON_CreateObject();
char * p = config_alloc_get_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
cJSON_AddBoolToObject(values,"jack_behavior",(strcmp(p,"1") == 0 ||strcasecmp(p,"y") == 0));
FREE_AND_NULL(p);
return values;
}
void get_str_parm_json(struct arg_str * parm, cJSON * entry){
const char * name = parm->hdr.longopts?parm->hdr.longopts:parm->hdr.glossary;
if(parm->count>0){
@@ -468,7 +527,21 @@ static void register_i2s_config(void){
cmd_to_json_with_cb(&cmd,&i2s_cb);
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
}
static void register_spdif_config(void){
static void register_audio_config(void){
audio_args.jack_behavior = arg_str0("j", "jack_behavior","Headphones|Subwoofer","On supported DAC, determines the audio jack behavior. Selecting headphones will cause the external amp to be muted on insert, while selecting Subwoofer will keep the amp active all the time.");
audio_args.end = arg_end(6);
const esp_console_cmd_t cmd = {
.command = CFG_TYPE_AUDIO("general"),
.help = desc_audio,
.hint = NULL,
.func = &do_audio_cmd,
.argtable = &audio_args
};
cmd_to_json_with_cb(&cmd,&audio_cb);
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
}static void register_spdif_config(void){
spdif_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
spdif_args.clock = arg_int1(NULL,"clock","<n>","Clock GPIO. e.g. 33");
spdif_args.wordselect = arg_int1(NULL,"wordselect","<n>","Word Select GPIO. e.g. 25");
@@ -517,7 +590,7 @@ static void register_squeezelite_config(void){
squeezelite_args.rate = arg_int0("Z","max_rate", "<n>", "Report rate to server in helo as the maximum sample rate we can support");
squeezelite_args.end = arg_end(6);
const esp_console_cmd_t cmd = {
.command = CFG_TYPE_SYST("squeezelite"),
.command = CFG_TYPE_AUDIO("squeezelite"),
.help = desc_squeezelite,
.hint = NULL,
.func = &do_squeezelite_cmd,
@@ -528,6 +601,7 @@ static void register_squeezelite_config(void){
}
void register_config_cmd(void){
register_audio_config();
register_squeezelite_config();
register_i2s_config();
register_spdif_config();

View File

@@ -1,7 +1,7 @@
/* Console example — various system commands
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
@@ -50,7 +50,7 @@ static struct {
struct arg_str *telnet;
#if WITH_TASKS_INFO
struct arg_lit *stats;
#endif
#endif
struct arg_end *end;
} set_services_args;
static const char * TAG = "cmd_system";
@@ -127,30 +127,30 @@ static void register_version()
esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
{
if(is_recovery_running){
if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
log_send_messaging(MESSAGING_WARNING,"RECOVERY application is already active");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return ESP_OK;
}
}
else {
if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){
log_send_messaging(MESSAGING_WARNING,"SQUEEZELITE application is already active");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return ESP_OK;
}
}
if(is_recovery_running){
if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
log_send_messaging(MESSAGING_WARNING,"RECOVERY application is already active");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return ESP_OK;
}
}
else {
if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){
log_send_messaging(MESSAGING_WARNING,"SQUEEZELITE application is already active");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return ESP_OK;
}
}
esp_err_t err = ESP_OK;
bool bFound=false;
log_send_messaging(MESSAGING_INFO, "Looking for partition type %u",partition_subtype);
@@ -174,9 +174,7 @@ else {
log_send_messaging(MESSAGING_ERROR,"Unable to select partition for reboot: %s",esp_err_to_name(err));
}
else{
log_send_messaging(MESSAGING_WARNING, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
bFound=true;
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
bFound=true;
}
}
else
@@ -187,9 +185,8 @@ else {
ESP_LOGD(TAG, "Yielding to other processes");
taskYIELD();
if(bFound) {
log_send_messaging(MESSAGING_WARNING,"Configuration %s changes. ",config_has_changes()?"has":"does not have");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration changes. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();

View File

@@ -14,6 +14,7 @@
extern "C" {
#endif
#define CFG_TYPE_HW(a) "cfg-hw-" a
#define CFG_TYPE_AUDIO(a) "cfg-audio-" a
#define CFG_TYPE_SYST(a) "cfg-syst-" a
#define CFG_TYPE_FW(a) "cfg-fw-" a
#define CFG_TYPE_GEN(a) "cfg-gen-" a

View File

@@ -178,6 +178,9 @@ static void set_jack_gpio(int gpio, char *value) {
jack.gpio = gpio;
if ((p = strchr(value, ':')) != NULL) jack.active = atoi(p + 1);
}
else {
jack.gpio = -1;
}
}
#endif
@@ -191,6 +194,9 @@ static void set_spkfault_gpio(int gpio, char *value) {
spkfault.gpio = gpio;
if ((p = strchr(value, ':')) != NULL) spkfault.active = atoi(p + 1);
}
else {
spkfault.gpio = -1;
}
}
#endif

View File

@@ -2,7 +2,7 @@ idf_component_register( SRC_DIRS .
INCLUDE_DIRS . ${IDF_PATH}/components/esp_http_server/src ${IDF_PATH}/components/esp_http_server/src/port/esp32 ${IDF_PATH}/components/esp_http_server/src/util ${IDF_PATH}/components/esp_http_server/src/
REQUIRES squeezelite-ota json mdns
PRIV_REQUIRES tools services platform_config esp_common json newlib freertos spi_flash nvs_flash mdns pthread wpa_supplicant platform_console esp_http_server console
EMBED_FILES res/style.css.gz res/code.js.gz index.html res/bootstrap.css.gz res/jquery.js.gz res/bootstrap.js.gz res/favicon.ico
EMBED_FILES res/style.css.gz res/code.js.gz index.html res/bootstrap.css.gz res/yeti/bootstrap.css.gz res/jquery.js.gz res/bootstrap.js.gz res/favicon.ico
)

View File

@@ -201,7 +201,7 @@
<div class="tab-pane fade mt-2" id="tab-configuration">
<ul class="nav nav-tabs bg-info" name="secnav">
<li class="nav-link" style="padding: inherit; border: none;">
<a class="nav-link active" data-toggle="tab" href="#tab-audio">Audio + LMS</a>
<a class="nav-link active" data-toggle="tab" href="#tab-cfg-audio">Audio</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#tab-cfg-syst">System</a>
@@ -295,13 +295,13 @@
</div>
</div>
<div class="tab-pane fade active show" id="tab-audio">
<div class="tab-pane fade active show" id="tab-cfg-audio">
<div class="card text-white bg-primary mb-3">
<div class="card-header">Command Line Templates</div>
<div class="card-header">Usage Templates</div>
<div class="card-body">
<fieldset >
<fieldset class="form-group" id="output-tmpl">
<legend>Audio Output</legend>
<legend>Output</legend>
<div class="form-check">
<label class="form-check-label">
<input type="radio" class="form-check-input" name="output-tmpl" id="i2s" >

File diff suppressed because one or more lines are too long

View File

@@ -72,6 +72,16 @@ var escapeHTML = function(unsafe) {
}
});
};
function setNavColor(stylename){
$('[name=secnav]').removeClass('bg-secondary bg-warning');
$("footer.footer").removeClass('bg-secondary bg-warning');
$("#mainnav").removeClass('bg-secondary bg-warning');
if(stylename.length>0){
$('[name=secnav]').addClass(stylename);
$("footer.footer").addClass(stylename);
$("#mainnav").addClass(stylename);
}
}
function handleTemplateTypeRadio(outtype){
if (outtype == 'bt') {
$("#btsinkdiv").parent().show(200);
@@ -103,6 +113,7 @@ function handleTemplateTypeRadio(outtype){
function handleExceptionResponse(xhr, ajaxOptions, thrownError){
console.log(xhr.status);
console.log(thrownError);
enableStatusTimer=true;
if (thrownError != '') showLocalMessage(thrownError, 'MESSAGING_ERROR');
}
function HideCmdMessage(cmdname){
@@ -278,6 +289,8 @@ function onChooseFile(event, onLoadFileHandler) {
function delay_reboot(duration,cmdname, ota=false){
url= (ota?'/reboot_ota.json':'/reboot.json');
$("tbody#tasks").empty();
setNavColor('bg-secondary');
enableStatusTimer=false;
$("#tasks_sect").css('visibility','collapse');
Promise.resolve(cmdname).delay(duration).then(function(cmdname) {
if(cmdname?.length >0){
@@ -299,6 +312,7 @@ function delay_reboot(duration,cmdname, ota=false){
error: handleExceptionResponse,
complete: function(response) {
console.log('reboot call completed');
enableStatusTimer=true;
Promise.resolve(cmdname).delay(6000).then(function(cmdname) {
if(cmdname?.length >0) HideCmdMessage(cmdname);
getCommands();
@@ -547,6 +561,9 @@ $(document).ready(function() {
});
$("#fwUpload").on("click", function() {
var upload_path = "/flash.json";
if(!recovery) $('#flash-status').text('Rebooting to OTA');
var fileInput = document.getElementById("flashfilename").files;
if (fileInput.length == 0) {
alert("No file selected!");
@@ -919,9 +936,7 @@ function handleRecoveryMode(data){
$("#otadiv").show();
$('#uploaddiv').show();
$("footer.footer").removeClass('sl');
$("footer.footer").addClass('bg-warning');
$("#mainnav").addClass('bg-warning');
$('[name=secnav]').addClass('bg-warning');
setNavColor('bg-warning');
$("#boot-button").html('Reboot');
$("#boot-form").attr('action', '/reboot_ota.json');
} else {
@@ -930,9 +945,7 @@ function handleRecoveryMode(data){
$("#reboot_nav").show();
$("#otadiv").hide();
$('#uploaddiv').hide();
$("footer.footer").removeClass('bg-warning');
$('#mainnav').removeClass('bg-warning');
$('[name=secnav]').removeClass('bg-warning');
setNavColor('');
$("footer.footer").addClass('sl');
$("#boot-button").html('Recovery');
$("#boot-form").attr('action', '/recovery.json');