|
@@ -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();
|