static const char *TAG = "presets"; #include #include #include "presets.hpp" #include "utils.hpp" namespace Presets { /* Preset Map */ std::map map; const Pattern* find(const std::string &name) { auto e = map.find(name); return e == map.end() ? NULL : e->second; } std::map::const_iterator map_begin() { return map.begin(); } std::map::const_iterator map_end() { return map.end(); } static inline cJSON* load_json(const char *path) { return cJSON_Parse(read_file(path).c_str()); } /* Preset Loader */ static Color json_raw_color(cJSON *json) { if (json->type != cJSON_Array) { ESP_LOGE(TAG, "Not an array: %s", json->string); return {0, 0, 0}; } int count = cJSON_GetArraySize(json); if (count != 3) { ESP_LOGE(TAG, "Wrong size for %s: %d", json->string, count); return {0, 0, 0}; } // TODO: Number checks for array elements? return Color{ (uint8_t)cJSON_GetArrayItem(json, 0)->valueint, (uint8_t)cJSON_GetArrayItem(json, 1)->valueint, (uint8_t)cJSON_GetArrayItem(json, 2)->valueint }; } static Color json_color(cJSON *json, const std::map &colors) { if (json->type == cJSON_Array) return json_raw_color(json); if (json->type != cJSON_String) { ESP_LOGE(TAG, "Not a string: %s", json->string); return {0, 0, 0}; } auto iter = colors.find(json->valuestring); if (iter == colors.end()) { ESP_LOGE(TAG, "Not a color: %s", json->valuestring); return {0, 0, 0}; } return iter->second; } static Pattern* json_pattern(cJSON *json, const std::map &colors) { if (json->type != cJSON_Object) { ESP_LOGE(TAG, "Not an object: %s", json->string); return NULL; } cJSON *pattern = json->child; std::string type(pattern->string); if (type == "gradient") { if (pattern->type != cJSON_Object) { ESP_LOGE(TAG, "Not an object: %s", pattern->type); return NULL; } cJSON *jcolors = cJSON_GetObjectItem(pattern, "colors"); if (!jcolors) { ESP_LOGE(TAG, "No colors for %s", json->string); return NULL; } if (jcolors->type != cJSON_Array) { ESP_LOGE(TAG, "Not an array: %s", jcolors->string); return NULL; } Gradient *gradient = Gradient::make(cJSON_GetArraySize(jcolors)); int i = 0; cJSON *jcolor; cJSON_ArrayForEach(jcolor, jcolors) { Color color = json_color(jcolor, colors); gradient->colors[i++] = color; } return new GradientPattern(gradient); } else { ESP_LOGE(TAG, "Unknown pattern type: %s", type.c_str()); } return NULL; } void reload() { std::map colors; cJSON *jcolors = load_json("/spiffs/colors.json"); if (!jcolors) { ESP_LOGW(TAG, "No preset colors!"); } else { cJSON *jcolor; cJSON_ArrayForEach(jcolor, jcolors) { Color color = json_color(jcolor, colors); colors[jcolor->string] = color; } cJSON_Delete(jcolors); } for (const auto &k_v : map) delete k_v.second; map.clear(); cJSON *jpresets = load_json("/spiffs/presets.json"); if (!jpresets) { ESP_LOGE(TAG, "No preset patterns!"); } else { cJSON *jpreset; cJSON_ArrayForEach(jpreset, jpresets) { Pattern *pattern = json_pattern(jpreset, colors); if (pattern) { ESP_LOGI(TAG, "Creating preset: %s", jpreset->string); map[jpreset->string] = pattern; } } cJSON_Delete(jpresets); } } } // Presets