diff --git a/components/services/audio_controls.c b/components/services/audio_controls.c
index 855f80af..30794e70 100644
--- a/components/services/audio_controls.c
+++ b/components/services/audio_controls.c
@@ -18,7 +18,7 @@
* along with this program. If not, see .
*
*/
-
+ #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include
#include
#include
@@ -26,6 +26,7 @@
#include "esp_log.h"
#include "cJSON.h"
#include "buttons.h"
+#include "config.h"
#include "audio_controls.h"
@@ -36,6 +37,8 @@ typedef struct {
actrls_config_map_handler * handler;
} actrls_config_map_t;
+
+
static esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_config);
static esp_err_t actrls_process_button(const cJSON * button, actrls_config_t *cur_config);
static esp_err_t actrls_process_int (const cJSON * member, actrls_config_t *cur_config, uint32_t offset);
@@ -66,34 +69,56 @@ static const char * actrls_action_s[ ] = { EP(ACTRLS_VOLUP),EP(ACTRLS_VOLDOWN),E
static const char * TAG = "audio controls";
static actrls_config_t *json_config;
+cJSON * control_profiles = NULL;
static actrls_t default_controls, current_controls;
static void control_handler(void *client, button_event_e event, button_press_e press, bool long_press) {
actrls_config_t *key = (actrls_config_t*) client;
- actrls_action_e action;
+ actrls_action_detail_t action_detail;
switch(press) {
case BUTTON_NORMAL:
- if (long_press) action = key->longpress[event == BUTTON_PRESSED ? 0 : 1].action;
- else action = key->normal[event == BUTTON_PRESSED ? 0 : 1].action;
+ if (long_press) action_detail = key->longpress[event == BUTTON_PRESSED ? 0 : 1];
+ else action_detail = key->normal[event == BUTTON_PRESSED ? 0 : 1];
break;
case BUTTON_SHIFTED:
- if (long_press) action = key->longshifted[event == BUTTON_PRESSED ? 0 : 1].action;
- else action = key->shifted[event == BUTTON_PRESSED ? 0 : 1].action;
+ if (long_press) action_detail = key->longshifted[event == BUTTON_PRESSED ? 0 : 1];
+ else action_detail = key->shifted[event == BUTTON_PRESSED ? 0 : 1];
break;
default:
- action = ACTRLS_NONE;
+ action_detail.action = ACTRLS_NONE;
break;
}
- ESP_LOGD(TAG, "control gpio:%u press:%u long:%u event:%u action:%u", key->gpio, press, long_press, event, action);
+ ESP_LOGD(TAG, "control gpio:%u press:%u long:%u event:%u action:%u", key->gpio, press, long_press, event,action_detail.action);
- if (action > ACTRLS_MAX) {
- // need to do the remap here using button_remap
- ESP_LOGD(TAG, "remapping buttons");
- } else if (action != ACTRLS_NONE) {
- ESP_LOGD(TAG, "calling action %u", action);
- if (current_controls[action]) (*current_controls[action])();
+ if (action_detail.action == ACTRLS_REMAP) {
+ // remap requested
+ ESP_LOGD(TAG, "remapping buttons to profile %s",action_detail.name);
+ cJSON * profile_obj = cJSON_GetObjectItem(control_profiles,action_detail.name);
+ if(profile_obj){
+ actrls_config_t * profile = (actrls_config_t *) cJSON_GetStringValue(profile_obj);
+ if(profile){
+ actrls_config_t *cur_config =profile;
+ ESP_LOGD(TAG,"Remapping all the buttons that are found in the new profile");
+ while(cur_config){
+ ESP_LOGD(TAG,"Remapping button with gpio %u", cur_config->gpio);
+ button_remap((void*) cur_config, cur_config->gpio, control_handler, cur_config->long_press, cur_config->shifter_gpio);
+ cur_config++;
+ }
+ }
+ else {
+ ESP_LOGE(TAG,"Profile %s exists, but is empty. Cannot remap buttons",action_detail.name);
+ }
+
+ }
+ else {
+ ESP_LOGE(TAG,"Invalid profile name %s. Cannot remap buttons",action_detail.name);
+ }
+
+ } else if (action_detail.action != ACTRLS_NONE) {
+ ESP_LOGD(TAG, "calling action %u", action_detail.action);
+ if (current_controls[action_detail.action]) (*current_controls[action_detail.action])();
}
}
@@ -137,13 +162,30 @@ esp_err_t actrls_init(int n, const actrls_config_t *config) {
*
*/
static actrls_action_e actrls_parse_action_json(const char * name){
-
+ actrls_action_e action = ACTRLS_NONE;
+ if(!strcmp("ACTRLS_NONE",name)) return ACTRLS_NONE;
for(int i=0;ivaluestring);
+ value[0].action = actrls_parse_action_json( button_action->valuestring);
+ if(value[0].action == ACTRLS_REMAP){
+ value[0].name = strdup(button_action->valuestring);
+ }
}
else{
ESP_LOGW(TAG,"Action pressed not found in json structure");
@@ -217,7 +262,10 @@ static esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *c
}
button_action = cJSON_GetObjectItemCaseSensitive(member, "released");
if (button_action != NULL) {
- value[1] = actrls_parse_action_json( button_action->valuestring);
+ value[1].action = actrls_parse_action_json( button_action->valuestring);
+ if(value[1].action == ACTRLS_REMAP){
+ value[1].name = strdup(button_action->valuestring);
+ }
}
else{
ESP_LOGW(TAG,"Action released not found in json structure");
@@ -269,20 +317,28 @@ static esp_err_t actrls_process_button(const cJSON * button, actrls_config_t *cu
/****************************************************************************************
*
*/
-static actrls_config_t * actrls_init_alloc_structure(const cJSON *buttons){
+static actrls_config_t * actrls_init_alloc_structure(const cJSON *buttons, const char * name){
int member_count = 0;
const cJSON *button;
actrls_config_t * json_config=NULL;
+
+ // Check if the main profiles array was created
+ if(!control_profiles){
+ control_profiles = cJSON_CreateObject();
+ }
+
+
ESP_LOGD(TAG,"Counting the number of buttons definition");
cJSON_ArrayForEach(button, buttons) {
member_count++;
}
+
ESP_LOGD(TAG, "config contains %u button definitions",
member_count);
if (member_count != 0) {
- json_config = malloc(sizeof(actrls_config_t) * member_count);
+ json_config = malloc(sizeof(actrls_config_t) * member_count+1);
if(json_config){
- memset(json_config, 0x00, sizeof(actrls_config_t) * member_count);
+ memset(json_config, 0x00, sizeof(actrls_config_t) * member_count+1);
}
else {
ESP_LOGE(TAG,"Unable to allocate memory to hold configuration for %u buttons ",member_count);
@@ -293,17 +349,31 @@ static actrls_config_t * actrls_init_alloc_structure(const cJSON *buttons){
ESP_LOGE(TAG,"No button found in configuration structure");
}
+ // we're cheating here; we're going to store the control profile
+ // pointer as a string reference; this will prevent cJSON
+ // from trying to free the structure if we ever want to free the object
+ cJSON * new_profile = cJSON_CreateStringReference((const char *)json_config);
+ cJSON_AddItemToObject(control_profiles, name, new_profile);
+
+
return json_config;
}
+
/****************************************************************************************
*
*/
-esp_err_t actrls_init_json(const char *config) {
+esp_err_t actrls_init_json(const char *profile_name) {
esp_err_t err = ESP_OK;
- actrls_config_t *cur_config;
+ actrls_config_t *cur_config = NULL;
+ actrls_config_t *config_root = NULL;
const cJSON *button;
- ESP_LOGD(TAG,"Parsing JSON structure ");
+
+
+ char *config = config_alloc_get_default(NVS_TYPE_STR, profile_name, NULL, 0);
+ if(!config) return ESP_FAIL;
+
+ ESP_LOGD(TAG,"Parsing JSON structure %s", config);
cJSON *buttons = cJSON_Parse(config);
if (buttons == NULL) {
ESP_LOGE(TAG,"JSON Parsing failed for %s", config);
@@ -313,7 +383,7 @@ esp_err_t actrls_init_json(const char *config) {
ESP_LOGD(TAG,"Json parsing completed");
if (cJSON_IsArray(buttons)) {
ESP_LOGD(TAG,"configuration is an array as expected");
- cur_config = json_config = actrls_init_alloc_structure(buttons);
+ cur_config =config_root= actrls_init_alloc_structure(buttons, profile_name);
if(!cur_config) {
ESP_LOGE(TAG,"Config buffer was empty. ");
cJSON_Delete(buttons);
@@ -344,6 +414,10 @@ esp_err_t actrls_init_json(const char *config) {
}
cJSON_Delete(buttons);
}
+ // Now update the global json_config object. If we are recursively processing menu structures,
+ // the last init that completes will assigh the first json config object found, which will match
+ // the default config from nvs.
+ json_config = config_root;
return err;
}
diff --git a/components/services/audio_controls.h b/components/services/audio_controls.h
index 2a63f1df..c73c96f9 100644
--- a/components/services/audio_controls.h
+++ b/components/services/audio_controls.h
@@ -23,7 +23,7 @@
// BEWARE: this is the index of the array of action below (change actrls_action_s as well!)
typedef enum { ACTRLS_NONE = -1, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
- BCTRLS_PUSH, BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
+ BCTRLS_PUSH, BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,ACTRLS_REMAP,
ACTRLS_MAX
} actrls_action_e;
@@ -31,6 +31,10 @@ typedef void (*actrls_handler)(void);
typedef actrls_handler actrls_t[ACTRLS_MAX - ACTRLS_NONE - 1];
// BEWARE any change to struct below must be mapped to actrls_config_map
+typedef struct {
+ actrls_action_e action;
+ const char * name;
+} actrls_action_detail_t;
typedef struct actrl_config_s {
int gpio;
int type;
@@ -38,14 +42,11 @@ typedef struct actrl_config_s {
int debounce;
int long_press;
int shifter_gpio;
- union {
- actrls_action_e action;
- struct actrl_config_s *config;
- } normal[2], longpress[2], shifted[2], longshifted[2]; // [0] keypressed, [1] keyreleased
+ actrls_action_detail_t normal[2], longpress[2], shifted[2], longshifted[2]; // [0] keypressed, [1] keyreleased
} actrls_config_t;
esp_err_t actrls_init(int n, const actrls_config_t *config);
-esp_err_t actrls_init_json(const char * config);
+esp_err_t actrls_init_json(const char *profile_name);
void actrls_set_default(const actrls_t controls);
void actrls_set(const actrls_t controls);
void actrls_unset(void);
diff --git a/main/esp_app_main.c b/main/esp_app_main.c
index 83f35a93..623fa03a 100644
--- a/main/esp_app_main.c
+++ b/main/esp_app_main.c
@@ -367,16 +367,7 @@ void app_main()
if (actrls_brd) {
if(actrls_brd[0] !='\0'){
ESP_LOGD(TAG,"Initializing audio control buttons type %s", actrls_brd);
- char *actrls_brd_json = config_alloc_get_default(NVS_TYPE_STR, actrls_brd, NULL, 0);
-
- if(actrls_brd_json){
- ESP_LOGD(TAG,"with config JSON as follow: %s", actrls_brd_json );
- actrls_init_json(actrls_brd_json);
- free(actrls_brd_json);
- }
- else {
- ESP_LOGE(TAG,"Audio controls board type %s could not be found",actrls_brd);
- }
+ actrls_init_json(actrls_brd);
}
free(actrls_brd);
} else {