Hardware mirror in the ST7789 (rotation 3 <-> rotation 1); the 35-px window offset is the same both ways. Stored in settings v3.
133 lines
4.5 KiB
C
133 lines
4.5 KiB
C
#include "settings.h"
|
|
#include "ui.h"
|
|
#include "sdkconfig.h"
|
|
#include "esp_log.h"
|
|
#include "nvs.h"
|
|
#include "nvs_flash.h"
|
|
#include "esp_heap_caps.h"
|
|
#include <assert.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
static const char *TAG = "settings";
|
|
static nvs_handle_t nvs;
|
|
settings_t settings;
|
|
static cam_info_t *favs; // FAV_SLOTS entries, in PSRAM
|
|
static bool fav_used[FAV_SLOTS];
|
|
|
|
static void slot_key(int slot, char *key) { snprintf(key, 8, "fav%d", slot); }
|
|
|
|
void settings_init(void)
|
|
{
|
|
esp_err_t err = nvs_flash_init();
|
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
err = nvs_flash_init();
|
|
}
|
|
ESP_ERROR_CHECK(err);
|
|
ESP_ERROR_CHECK(nvs_open("widget", NVS_READWRITE, &nvs));
|
|
|
|
settings = (settings_t){
|
|
.interval_s = CONFIG_WIDGET_INTERVAL_S, .lcd_brightness = CONFIG_WIDGET_LCD_BRIGHTNESS,
|
|
.led_brightness = CONFIG_WIDGET_LED_BRIGHTNESS,
|
|
#if CONFIG_WIDGET_LISTING_RATING
|
|
.listing = LISTING_RATING,
|
|
#elif CONFIG_WIDGET_LISTING_NEW
|
|
.listing = LISTING_NEW,
|
|
#else
|
|
.listing = LISTING_MIXED,
|
|
#endif
|
|
.source = SOURCE_RANDOM, .caption = 1, .provider = PROVIDER_PREF_MIXED, .version = SETTINGS_VERSION,
|
|
};
|
|
// Blobs written by older builds may be shorter: copy what is there over the defaults.
|
|
settings_t stored = settings;
|
|
size_t len = sizeof stored;
|
|
if (nvs_get_blob(nvs, "settings", &stored, &len) == ESP_OK && len >= 7 && len <= sizeof stored) {
|
|
memcpy(&settings, &stored, len);
|
|
if (len <= offsetof(settings_t, provider)) settings.provider = PROVIDER_PREF_MIXED; // pre-provider blob
|
|
if (settings.version < 3) settings.flip = 0; // field lived in padding before v3
|
|
settings.flip = settings.flip ? 1 : 0;
|
|
settings.version = SETTINGS_VERSION;
|
|
if (settings.interval_s < 5 || settings.interval_s > 300) settings.interval_s = CONFIG_WIDGET_INTERVAL_S;
|
|
if (settings.lcd_brightness > 100) settings.lcd_brightness = 100;
|
|
if (settings.listing > LISTING_NEW) settings.listing = LISTING_MIXED;
|
|
if (settings.source > SOURCE_POPULAR) settings.source = SOURCE_RANDOM;
|
|
if (settings.theme >= ui_theme_count()) settings.theme = 0;
|
|
if (settings.provider > PROVIDER_PREF_MIXED) settings.provider = PROVIDER_PREF_MIXED;
|
|
}
|
|
favs = heap_caps_calloc(FAV_SLOTS, sizeof *favs, MALLOC_CAP_SPIRAM);
|
|
assert(favs);
|
|
for (int i = 0; i < FAV_SLOTS; i++) {
|
|
char key[8];
|
|
slot_key(i, key);
|
|
len = sizeof favs[i];
|
|
fav_used[i] = nvs_get_blob(nvs, key, &favs[i], &len) == ESP_OK && len <= sizeof favs[i] && favs[i].url[0];
|
|
if (fav_used[i] && favs[i].provider > PROVIDER_OPENTOPIA) favs[i].provider = PROVIDER_INSECAM;
|
|
}
|
|
ESP_LOGI(TAG, "interval %us, lcd %u%%, ring %u, listing %u, source %u, provider %u, %d favourites",
|
|
settings.interval_s, settings.lcd_brightness, settings.led_brightness, settings.listing,
|
|
settings.source, settings.provider, fav_count());
|
|
}
|
|
|
|
void settings_save(void)
|
|
{
|
|
if (nvs_set_blob(nvs, "settings", &settings, sizeof settings) != ESP_OK || nvs_commit(nvs) != ESP_OK)
|
|
ESP_LOGW(TAG, "save failed");
|
|
}
|
|
|
|
void settings_request_portal(void)
|
|
{
|
|
nvs_set_u8(nvs, "portal", 1);
|
|
nvs_commit(nvs);
|
|
}
|
|
|
|
bool settings_take_portal_request(void)
|
|
{
|
|
uint8_t v = 0;
|
|
if (nvs_get_u8(nvs, "portal", &v) != ESP_OK || !v) return false;
|
|
nvs_erase_key(nvs, "portal");
|
|
nvs_commit(nvs);
|
|
return true;
|
|
}
|
|
|
|
const cam_info_t *fav_get(int slot)
|
|
{
|
|
return (slot >= 0 && slot < FAV_SLOTS && fav_used[slot]) ? &favs[slot] : NULL;
|
|
}
|
|
|
|
void fav_set(int slot, const cam_info_t *cam)
|
|
{
|
|
if (slot < 0 || slot >= FAV_SLOTS) return;
|
|
char key[8];
|
|
slot_key(slot, key);
|
|
favs[slot] = *cam;
|
|
fav_used[slot] = true;
|
|
if (nvs_set_blob(nvs, key, &favs[slot], sizeof favs[slot]) != ESP_OK || nvs_commit(nvs) != ESP_OK)
|
|
ESP_LOGW(TAG, "favourite %d not saved", slot);
|
|
}
|
|
|
|
void fav_clear(int slot)
|
|
{
|
|
if (slot < 0 || slot >= FAV_SLOTS) return;
|
|
char key[8];
|
|
slot_key(slot, key);
|
|
fav_used[slot] = false;
|
|
nvs_erase_key(nvs, key);
|
|
nvs_commit(nvs);
|
|
}
|
|
|
|
int fav_find(const cam_info_t *cam)
|
|
{
|
|
for (int i = 0; i < FAV_SLOTS; i++)
|
|
if (fav_used[i] && favs[i].id == cam->id && favs[i].provider == cam->provider) return i;
|
|
return -1;
|
|
}
|
|
|
|
int fav_count(void)
|
|
{
|
|
int n = 0;
|
|
for (int i = 0; i < FAV_SLOTS; i++) n += fav_used[i];
|
|
return n;
|
|
}
|