summaryrefslogtreecommitdiff
path: root/src/c/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/c/config.c')
-rw-r--r--src/c/config.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/c/config.c b/src/c/config.c
new file mode 100644
index 0000000..0791b85
--- /dev/null
+++ b/src/c/config.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2026 Reiner Herrmann
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <pebble.h>
+#include "config.h"
+#include "metronome.h"
+
+struct Configuration {
+ uint8_t version;
+ uint16_t bpm;
+ uint8_t beats;
+ uint8_t volume;
+ uint8_t beat_indicators;
+} __attribute__((__packed__));
+
+#define SETTINGS_KEY 1
+#define CONFIG_VERSION 1
+
+static struct Configuration configuration;
+
+static void config_persist() {
+ persist_write_data(SETTINGS_KEY, &configuration, sizeof(configuration));
+}
+
+static void config_load_defaults() {
+ configuration.version = CONFIG_VERSION;
+ configuration.bpm = 90;
+ configuration.beats = 4;
+ configuration.volume = 100;
+ configuration.beat_indicators = 0xff;
+}
+
+static void config_load() {
+ config_load_defaults();
+
+ /* buffer remains unchanged if no data is persisted */
+ persist_read_data(SETTINGS_KEY, &configuration, sizeof(configuration));
+
+ if (configuration.version != CONFIG_VERSION) {
+ /* unknown persisted configuration format */
+ config_load_defaults();
+ }
+}
+
+static void config_inbox_received_handler(DictionaryIterator *iter, void *context) {
+ struct Configuration new_configuration;
+ memcpy(&new_configuration, &configuration, sizeof(configuration));
+
+ Tuple *bpm_tuple = dict_find(iter, MESSAGE_KEY_bpm);
+ if (bpm_tuple) {
+ int32_t bpm = bpm_tuple->value->int32;
+ configuration.bpm = (uint16_t) bpm;
+ }
+
+ Tuple *beats_tuple = dict_find(iter, MESSAGE_KEY_beats);
+ if (beats_tuple) {
+ int32_t beats = beats_tuple->value->int32;
+ configuration.beats = (uint8_t) beats;
+ }
+
+ Tuple *volume_tuple = dict_find(iter, MESSAGE_KEY_volume);
+ if (volume_tuple) {
+ int32_t volume = volume_tuple->value->int32;
+ configuration.volume = (uint8_t) volume;
+ }
+
+ const int num_beat_indicators = 3;
+ for (int i=0; i<num_beat_indicators; i++) {
+ Tuple *beat_indicator = dict_find(iter, MESSAGE_KEY_beat_indicators + i);
+ if (beat_indicator) {
+ bool val = beat_indicator->value->uint8;
+ /* clear bit */
+ configuration.beat_indicators &= ~(1 << i);
+ /* set value into bit */
+ configuration.beat_indicators |= (val << i);
+ }
+ }
+
+ if (memcmp(&new_configuration, &configuration, sizeof(configuration)) != 0) {
+ /* only persist if something changed */
+ config_persist();
+
+ update_display();
+ }
+}
+
+void config_init() {
+ config_load();
+
+ app_message_register_inbox_received(config_inbox_received_handler);
+ app_message_open(128, 128);
+}
+
+void config_deinit() {
+ app_message_deregister_callbacks();
+}
+
+uint16_t config_get_bpm() {
+ return configuration.bpm;
+}
+
+void config_set_bpm(uint16_t bpm) {
+ configuration.bpm = bpm;
+ config_persist();
+}
+
+uint8_t config_get_beats() {
+ return configuration.beats;
+}
+
+void config_set_beats(uint8_t beats) {
+ configuration.beats = beats;
+ config_persist();
+}
+
+uint8_t config_get_volume() {
+ return configuration.volume;
+}
+
+bool config_is_indicator_enabled(enum BeatIndicator indicator) {
+ return configuration.beat_indicators & (1 << indicator);
+}