| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744 |
- // An intervalometer application written for the Flipper Zero
- //
- // author: nitepone <sierra>
- #include "intervalometer.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <furi.h>
- #include <furi_hal.h>
- #include <core/string.h>
- #include <gui/gui.h>
- #include <gui/elements.h>
- #include <gui/icon.h>
- #include <infrared_transmit.h>
- #include <infrared/infrared_last_settings.h>
- #include <input/input.h>
- #include <notification/notification.h>
- #include <notification/notification_messages.h>
- #include <ir_intervalometer_icons.h>
- // app ui scenes
- enum flipvalo_ui_scene {
- FVSceneMain,
- FVSceneConfig,
- };
- // defines a flipvalo camera trigger
- struct flipvalo_trigger {
- const char* display_name;
- int (*send)(void* output_config);
- };
- enum flipvalo_trigger_variants {
- FvTrigMin = 0,
- FvTrigSony = 0,
- FvTrigCanon = 1,
- FvTrigNikon = 2,
- FvTrigMax = 2,
- };
- // run config for intervalometer
- struct flipvalo_config {
- int init_delay_msec; // initial delay to start capture
- int interval_delay_msec; // time between shots
- int shot_count; // total shots in run
- int burst_count; // number of triggers in a shot
- int burst_delay_msec; // time between triggers in a shot
- int tickrate; // tick rate in "ticks per second"
- enum flipvalo_trigger_variants trigger; // current trigger
- void* output_config;
- };
- // run time states for intervalometer
- enum flipvalo_state {
- FVDone = 0, // done, 0 so it is default if state struct is zeroed
- FVWaitInitShot, // waiting for first shot
- FVWaitContShot, // waiting between "bursts" or "shots"
- FVWaitBurst, // waiting between shots in a "burst"
- };
- // run time data for intervalometer
- // (this can be safely cleared between runs of the intervalometer)
- struct flipvalo_run_state {
- enum flipvalo_state state; // current state of the run
- int tick_cur; // current tick count
- int tick_next; // tick when next action will occur
- int shot_cur; // current shot
- int burst_cur; // current trigger in a burst
- };
- enum flipvalo_config_edit_lines {
- FvConfigEditInitDelay,
- FvConfigEditMIN = FvConfigEditInitDelay,
- FvConfigEditShotCount,
- FvConfigEditShotDelay,
- FvConfigEditBurstCount,
- FvConfigEditBurstDelay,
- FvConfigEditTrigger,
- FvConfigEditMAX = FvConfigEditTrigger,
- };
- struct flipvalo_config_edit_view {
- // the `config` that is under edit
- struct flipvalo_config* config;
- // the `cur_index` of the selection
- // (e.g. editing the 3rd value of a number)
- int cur_index;
- // the `cur_line` of the selection
- enum flipvalo_config_edit_lines cur_line;
- // the current line that is at the top of the scrolled view
- enum flipvalo_config_edit_lines scroll_pos;
- // are we editing the selection?
- // (this is really only needed for number fields)
- bool edit_mode;
- };
- // private data of app
- struct flipvalo_priv {
- struct flipvalo_config config;
- struct flipvalo_config_edit_view config_edit_view;
- struct flipvalo_run_state run_state;
- enum flipvalo_ui_scene ui_scene;
- int gui_shutter_blink;
- FuriTimer* timer;
- NotificationApp* notifications;
- FuriMutex* mutex;
- };
- enum event_type {
- EventTypeTick,
- EventTypeKey,
- };
- struct plugin_event {
- enum event_type type;
- InputEvent input;
- };
- enum flipvalo_config_edit_line_type {
- FvConfigEditTypeTimer,
- FvConfigEditTypeCount,
- FvConfigEditTypeEnum,
- };
- static void flipvalo_config_edit_view_init(struct flipvalo_config_edit_view* view) {
- view->config = NULL;
- view->cur_index = 0;
- view->cur_line = 0;
- view->scroll_pos = 0;
- view->edit_mode = false;
- }
- static int sony_ir_trigger_send(void* ctx) {
- UNUSED(ctx);
- InfraredMessage message = {
- .address = 0x1E3A,
- .command = 0x2D,
- .protocol = InfraredProtocolSIRC20,
- };
- infrared_send(&message, 1);
- return 0;
- }
- uint32_t canon_ir_timings[] = {594, 7182, 593};
- static int canon_ir_trigger_send(void* ctx) {
- UNUSED(ctx);
- infrared_send_raw_ext(canon_ir_timings, 3, true, 38000, 0.33);
- return 0;
- }
- uint32_t nikon_ir_timings[] =
- {1945, 28253, 404, 1513, 410, 3611, 460, 70144, 1974, 28213, 455, 1493, 461, 3591, 409};
- static int nikon_ir_trigger_send(void* ctx) {
- UNUSED(ctx);
- infrared_send_raw_ext(nikon_ir_timings, 15, true, 38000, 0.33);
- return 0;
- }
- struct flipvalo_trigger sony_ir_trigger = {.send = sony_ir_trigger_send, .display_name = "Sony IR"};
- struct flipvalo_trigger canon_ir_trigger = {
- .send = canon_ir_trigger_send,
- .display_name = "Canon IR"};
- struct flipvalo_trigger nikon_ir_trigger = {
- .send = nikon_ir_trigger_send,
- .display_name = "Nikon IR"};
- static struct flipvalo_trigger* flipvalo_get_trigger(enum flipvalo_trigger_variants variant) {
- switch(variant) {
- case FvTrigSony:
- return &sony_ir_trigger;
- case FvTrigCanon:
- return &canon_ir_trigger;
- case FvTrigNikon:
- return &nikon_ir_trigger;
- }
- return NULL;
- }
- #define ITEM_H 64 / 3
- #define ITEM_W 128
- #define VALUE_X 100
- #define VALUE_W 45
- static void flipvalo_config_edit_draw(Canvas* canvas, struct flipvalo_config_edit_view* view) {
- int* line_value;
- char* line_label = NULL;
- const char* line_disp_str = "";
- FuriString* temp_str = furi_string_alloc();
- enum flipvalo_config_edit_line_type line_type;
- enum flipvalo_config_edit_lines selected_line;
- for(size_t line = 0; line < 3; line++) {
- selected_line = view->scroll_pos + line;
- switch(selected_line) {
- case FvConfigEditInitDelay:
- line_value = &view->config->init_delay_msec;
- line_type = FvConfigEditTypeTimer;
- line_label = "Init Time";
- break;
- case FvConfigEditShotDelay:
- line_value = &view->config->interval_delay_msec;
- line_type = FvConfigEditTypeTimer;
- line_label = "Seq Time";
- break;
- case FvConfigEditShotCount:
- line_value = &view->config->shot_count;
- line_type = FvConfigEditTypeCount;
- line_label = "Seq Count";
- break;
- case FvConfigEditBurstDelay:
- line_value = &view->config->burst_delay_msec;
- line_type = FvConfigEditTypeTimer;
- line_label = "Brst Time";
- break;
- case FvConfigEditBurstCount:
- line_value = &view->config->burst_count;
- line_type = FvConfigEditTypeCount;
- line_label = "Brst Count";
- break;
- case FvConfigEditTrigger:
- line_value = NULL;
- line_type = FvConfigEditTypeEnum;
- line_label = "Trig Type";
- line_disp_str = flipvalo_get_trigger(view->config->trigger)->display_name;
- break;
- default:
- continue;
- };
- canvas_set_color(canvas, ColorBlack);
- if((selected_line) == view->cur_line) {
- elements_slightly_rounded_box(canvas, 0, ITEM_H * line + 1, ITEM_W, ITEM_H - 1);
- canvas_set_color(canvas, ColorWhite);
- }
- uint8_t text_y = ITEM_H * line + ITEM_H / 2 + 2;
- canvas_draw_str_aligned(canvas, 6, text_y, AlignLeft, AlignCenter, line_label);
- switch(line_type) {
- case FvConfigEditTypeTimer:
- furi_string_printf(
- temp_str,
- "%02d:%02d:%02d:%03d",
- *line_value / 3600000,
- (*line_value / 60000) % 60,
- (*line_value / 1000) % 60,
- *line_value % 1000);
- canvas_set_font(canvas, FontKeyboard);
- canvas_draw_str_aligned(
- canvas, 124, text_y, AlignRight, AlignCenter, furi_string_get_cstr(temp_str));
- canvas_set_font(canvas, FontSecondary);
- if(view->edit_mode && view->cur_line == selected_line) {
- switch(view->cur_index) {
- case 0:
- canvas_draw_icon(canvas, 117, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 117, text_y + 5, &I_ArrowDown_3x5);
- canvas_draw_icon(canvas, 112, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 112, text_y + 5, &I_ArrowDown_3x5);
- canvas_draw_icon(canvas, 107, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 107, text_y + 5, &I_ArrowDown_3x5);
- break;
- case 1:
- canvas_draw_icon(canvas, 93, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 93, text_y + 5, &I_ArrowDown_3x5);
- canvas_draw_icon(canvas, 89, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 89, text_y + 5, &I_ArrowDown_3x5);
- break;
- case 2:
- canvas_draw_icon(canvas, 75, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 75, text_y + 5, &I_ArrowDown_3x5);
- canvas_draw_icon(canvas, 71, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 71, text_y + 5, &I_ArrowDown_3x5);
- break;
- case 3:
- canvas_draw_icon(canvas, 57, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 57, text_y + 5, &I_ArrowDown_3x5);
- canvas_draw_icon(canvas, 53, text_y - 9, &I_ArrowUp_3x5);
- canvas_draw_icon(canvas, 53, text_y + 5, &I_ArrowDown_3x5);
- break;
- }
- }
- break;
- case FvConfigEditTypeCount:
- furi_string_printf(temp_str, "%d", *line_value);
- canvas_draw_str_aligned(
- canvas, VALUE_X, text_y, AlignCenter, AlignCenter, furi_string_get_cstr(temp_str));
- // TODO(luna) 0 values are actually more special for shot count and burst count.
- // former being infinite, latter being uh.. nothing? not allowed?.. review this logic later.
- if(*line_value > 0) {
- canvas_draw_str_aligned(
- canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<");
- }
- canvas_draw_str_aligned(
- canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">");
- break;
- case FvConfigEditTypeEnum:
- furi_string_printf(temp_str, "%s", line_disp_str);
- canvas_draw_str_aligned(
- canvas, VALUE_X, text_y, AlignCenter, AlignCenter, furi_string_get_cstr(temp_str));
- canvas_draw_str_aligned(
- canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<");
- canvas_draw_str_aligned(
- canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">");
- break;
- }
- }
- furi_string_free(temp_str);
- }
- static void
- flipvalo_config_edit_input_move_cursor(struct flipvalo_config_edit_view* view, int dx, int dy) {
- enum flipvalo_config_edit_lines new_line = 0;
- int* line_value = NULL;
- enum flipvalo_config_edit_line_type line_type;
- // only used for enum type
- int max_value;
- int min_value;
- switch(view->cur_line) {
- case FvConfigEditInitDelay:
- line_value = &view->config->init_delay_msec;
- line_type = FvConfigEditTypeTimer;
- break;
- case FvConfigEditShotDelay:
- line_value = &view->config->interval_delay_msec;
- line_type = FvConfigEditTypeTimer;
- break;
- case FvConfigEditShotCount:
- line_value = &view->config->shot_count;
- line_type = FvConfigEditTypeCount;
- break;
- case FvConfigEditBurstDelay:
- line_value = &view->config->burst_delay_msec;
- line_type = FvConfigEditTypeTimer;
- break;
- case FvConfigEditBurstCount:
- line_value = &view->config->burst_count;
- line_type = FvConfigEditTypeCount;
- break;
- case FvConfigEditTrigger:
- line_value = (int*)(&view->config->trigger);
- line_type = FvConfigEditTypeEnum;
- min_value = FvTrigMin;
- max_value = FvTrigMax;
- break;
- default:
- return;
- };
- if(!view->edit_mode) {
- // Do `dy` behaviors
- new_line = view->cur_line + dy;
- if(new_line > FvConfigEditMAX) {
- // Out of bound cursor. No-op.
- return;
- }
- view->cur_line = new_line;
- // Handle moving scroll position.
- if(new_line < view->scroll_pos) {
- view->scroll_pos = new_line;
- } else if(new_line >= (view->scroll_pos + 3)) {
- view->scroll_pos += dy;
- }
- // Do `dx` behavior
- switch(line_type) {
- case FvConfigEditTypeTimer:
- // no-op unless edit mode
- break;
- case FvConfigEditTypeCount:
- min_value = 0;
- max_value = INT_MAX;
- // fall through.
- case FvConfigEditTypeEnum:
- if((*line_value + dx) >= min_value && (*line_value + dx) <= max_value) {
- *line_value += dx;
- }
- break;
- }
- } else /* edit mode */ {
- switch(line_type) {
- case FvConfigEditTypeCount:
- case FvConfigEditTypeEnum:
- // If current line does not edit mode.. why are we in edit mode?
- // Reaching this would be a bug, so lets go back to normal mode.
- view->edit_mode = false;
- return;
- case FvConfigEditTypeTimer:
- switch(view->cur_index) {
- case 0:
- if(*line_value + (dy * -10) >= 0) {
- *line_value += (dy * -10);
- }
- break;
- case 1:
- if(*line_value + (dy * -1000) >= 0) {
- *line_value += (dy * -1000);
- }
- break;
- case 2:
- if(*line_value + (dy * -60000) >= 0) {
- *line_value += (dy * -60000);
- }
- break;
- case 3:
- if(*line_value + (dy * -3600000) >= 0) {
- *line_value += (dy * -3600000);
- }
- break;
- }
- view->cur_index -= dx;
- if(view->cur_index < 0) {
- view->cur_index = 0;
- }
- if(view->cur_index > 3) {
- view->cur_index = 3;
- }
- break;
- }
- }
- }
- static int flipvalo_config_edit_input(InputEvent* event, struct flipvalo_config_edit_view* view) {
- // ignore all but short and repeats
- if(!(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
- return 0;
- }
- switch(event->key) {
- case InputKeyRight:
- flipvalo_config_edit_input_move_cursor(view, 1, 0);
- break;
- case InputKeyLeft:
- flipvalo_config_edit_input_move_cursor(view, -1, 0);
- break;
- case InputKeyUp:
- flipvalo_config_edit_input_move_cursor(view, 0, -1);
- break;
- case InputKeyDown:
- flipvalo_config_edit_input_move_cursor(view, 0, 1);
- break;
- case InputKeyOk:
- //TODO(luna) Check if line supports edit mode before doing this.
- view->edit_mode = !view->edit_mode;
- break;
- case InputKeyBack:
- if(view->edit_mode) {
- view->edit_mode = false;
- } else {
- // exit config edit view
- return 1;
- }
- default:
- break;
- }
- return 0;
- }
- // XXX(luna) back to app
- static void flipvalo_run_state_init(struct flipvalo_run_state* fv_run_state) {
- fv_run_state->burst_cur = 1;
- fv_run_state->shot_cur = 1;
- fv_run_state->tick_next = 0;
- fv_run_state->state = FVDone;
- fv_run_state->tick_next = 0;
- fv_run_state->tick_cur = 0;
- }
- static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
- furi_assert(event_queue);
- struct plugin_event event = {.type = EventTypeKey, .input = *input_event};
- furi_message_queue_put(event_queue, &event, FuriWaitForever);
- }
- static inline bool flipvalo_intv_running(struct flipvalo_priv* fv_priv) {
- return fv_priv->run_state.state != FVDone;
- }
- static void flipvalo_intv_tick(struct flipvalo_priv* fv_priv) {
- struct flipvalo_config* conf = &fv_priv->config;
- struct flipvalo_run_state* run = &fv_priv->run_state;
- // check if action required
- if(run->tick_cur++ >= run->tick_next) {
- // call trigger function
- flipvalo_get_trigger(conf->trigger)->send(conf->output_config);
- fv_priv->gui_shutter_blink = 3;
- // end of burst, prepare next shot
- if(run->burst_cur >= conf->burst_count) {
- run->burst_cur = 1;
- run->shot_cur++;
- run->state = FVWaitContShot;
- run->tick_next = run->tick_cur + ((conf->interval_delay_msec * conf->tickrate) / 1000);
- } else /*continue burst */ {
- run->burst_cur++;
- run->state = FVWaitBurst;
- run->tick_next = run->tick_cur + ((conf->burst_delay_msec * conf->tickrate) / 1000);
- }
- }
- if(run->shot_cur > conf->shot_count) {
- run->state = FVDone;
- }
- }
- static void flipvalo_intv_stop(struct flipvalo_priv* fv_priv) {
- fv_priv->run_state.state = FVDone;
- }
- static void flipvalo_intv_start(struct flipvalo_priv* fv_priv) {
- // clear struct
- furi_assert(fv_priv);
- flipvalo_run_state_init(&fv_priv->run_state);
- fv_priv->run_state.state = FVWaitInitShot;
- fv_priv->run_state.tick_next =
- ((fv_priv->config.init_delay_msec * fv_priv->config.tickrate) / 1000);
- }
- static void timer_callback(void* ctx) {
- furi_assert(ctx);
- struct flipvalo_priv* fv_priv = ctx;
- furi_mutex_acquire(fv_priv->mutex, FuriWaitForever);
- if(flipvalo_intv_running(fv_priv)) {
- flipvalo_intv_tick(fv_priv);
- }
- furi_mutex_release(fv_priv->mutex);
- }
- static void render_callback(Canvas* const canvas, void* ctx) {
- furi_assert(ctx);
- struct flipvalo_priv* fv_priv = ctx;
- FuriString* temp_str = furi_string_alloc();
- furi_mutex_acquire(fv_priv->mutex, FuriWaitForever);
- // invert screen if blinking
- if(fv_priv->gui_shutter_blink > 0) {
- fv_priv->gui_shutter_blink--;
- canvas_draw_box(canvas, 0, 0, 127, 63);
- canvas_set_color(canvas, ColorWhite);
- }
- if(fv_priv->ui_scene == FVSceneMain) {
- int countdown_msec =
- (1000 * (fv_priv->run_state.tick_next - fv_priv->run_state.tick_cur)) /
- fv_priv->config.tickrate;
- int elapsed_msec = (1000 * fv_priv->run_state.tick_cur) / fv_priv->config.tickrate;
- canvas_draw_frame(canvas, 0, 0, 128, 64);
- // draw countdown
- canvas_set_font(canvas, FontPrimary);
- furi_string_printf(
- temp_str,
- "%02d:%02d:%02d:%03d",
- countdown_msec / 3600000,
- (countdown_msec / 60000) % 60,
- (countdown_msec / 1000) % 60,
- countdown_msec % 1000);
- canvas_draw_str_aligned(
- canvas, 64, 24, AlignCenter, AlignCenter, furi_string_get_cstr(temp_str));
- // draw top and bottom status bars
- canvas_set_font(canvas, FontSecondary);
- furi_string_printf(
- temp_str,
- "%02d:%02d:%02d",
- elapsed_msec / 3600000,
- (elapsed_msec / 60000) % 60,
- (elapsed_msec / 1000) % 60);
- canvas_draw_str_aligned(
- canvas, 4, 8, AlignLeft, AlignCenter, furi_string_get_cstr(temp_str));
- furi_string_printf(temp_str, "Shot: %d", fv_priv->run_state.shot_cur);
- canvas_draw_str_aligned(
- canvas, 124, 8, AlignRight, AlignCenter, furi_string_get_cstr(temp_str));
- elements_button_left(canvas, "Cfg");
- elements_button_right(canvas, "Snap");
- if(fv_priv->run_state.state == FVDone) {
- elements_button_center(canvas, "Start");
- } else {
- elements_button_center(canvas, "Stop ");
- }
- } else if(fv_priv->ui_scene == FVSceneConfig) {
- flipvalo_config_edit_draw(canvas, &fv_priv->config_edit_view);
- }
- furi_string_free(temp_str);
- furi_mutex_release(fv_priv->mutex);
- }
- static void flipvalo_config_init(struct flipvalo_config* fv_conf) {
- fv_conf->init_delay_msec = 2000;
- fv_conf->interval_delay_msec = 0;
- fv_conf->shot_count = 1;
- fv_conf->burst_count = 1;
- fv_conf->burst_delay_msec = 0;
- fv_conf->tickrate = 125;
- fv_conf->trigger = FvTrigSony;
- fv_conf->output_config = NULL;
- }
- static void flipvalo_priv_init(struct flipvalo_priv* fv_priv) {
- flipvalo_config_init(&fv_priv->config);
- flipvalo_config_edit_view_init(&fv_priv->config_edit_view);
- flipvalo_run_state_init(&fv_priv->run_state);
- fv_priv->gui_shutter_blink = 0;
- fv_priv->timer = NULL;
- fv_priv->notifications = NULL;
- fv_priv->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
- fv_priv->gui_shutter_blink = 0;
- }
- int32_t flipvalo_app() {
- int ret = 0;
- ViewPort* view_port = NULL;
- Gui* gui = NULL;
- FuriStatus event_status = {0};
- struct plugin_event event = {0};
- FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(struct plugin_event));
- struct flipvalo_priv* fv_priv = malloc(sizeof(*fv_priv));
- flipvalo_priv_init(fv_priv);
- InfraredLastSettings* last_settings = infrared_last_settings_alloc();
- infrared_last_settings_load(last_settings);
- infrared_last_settings_apply(last_settings);
- if(!fv_priv->mutex) {
- FURI_LOG_E("Flipvalo", "Cannot create mutex\r\n");
- ret = 1;
- goto cleanup;
- }
- view_port = view_port_alloc();
- view_port_draw_callback_set(view_port, render_callback, fv_priv);
- view_port_input_callback_set(view_port, input_callback, event_queue);
- fv_priv->timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, fv_priv);
- furi_timer_start(
- fv_priv->timer, (uint32_t)furi_kernel_get_tick_frequency() / fv_priv->config.tickrate);
- gui = furi_record_open("gui");
- gui_add_view_port(gui, view_port, GuiLayerFullscreen);
- while(true) {
- event_status = furi_message_queue_get(event_queue, &event, 100);
- furi_mutex_acquire(fv_priv->mutex, FuriWaitForever);
- // catch event_status that is not Ok
- if(event_status == FuriStatusErrorTimeout) {
- // timeout, ignore
- goto next_event;
- } else if(event_status != FuriStatusOk) {
- FURI_LOG_E("Flipvalo", "Event Queue Error: %d\r\n", event_status);
- goto next_event;
- // TODO(luna) evaluate if we should exit here.
- //goto cleanup;
- }
- // handle input
- if(/* long press back */
- event.type == EventTypeKey && event.input.type == InputTypeLong &&
- event.input.key == InputKeyBack) {
- goto cleanup;
- }
- switch(fv_priv->ui_scene) {
- case FVSceneMain:
- // TODO(luna) Maybe give this a function.. look howl clean FVSceneConfig is...
- if(event.type == EventTypeKey) {
- if(event.input.type == InputTypeShort || event.input.type == InputTypeLong) {
- switch(event.input.key) {
- case InputKeyUp:
- break;
- case InputKeyDown:
- break;
- case InputKeyLeft:
- flipvalo_intv_stop(fv_priv);
- fv_priv->config_edit_view.config = &fv_priv->config;
- fv_priv->ui_scene = FVSceneConfig;
- break;
- case InputKeyRight:
- fv_priv->gui_shutter_blink = 3;
- flipvalo_get_trigger(fv_priv->config.trigger)
- ->send(fv_priv->config.output_config);
- break;
- case InputKeyOk:
- if(flipvalo_intv_running(fv_priv)) {
- flipvalo_intv_stop(fv_priv);
- } else {
- flipvalo_intv_start(fv_priv);
- }
- break;
- case InputKeyMAX:
- break;
- case InputKeyBack:
- break;
- }
- }
- }
- break;
- case FVSceneConfig:
- ret = flipvalo_config_edit_input(&event.input, &fv_priv->config_edit_view);
- if(ret) {
- fv_priv->ui_scene = FVSceneMain;
- }
- break;
- }
- next_event:
- furi_mutex_release(fv_priv->mutex);
- view_port_update(view_port);
- }
- cleanup:
- if(view_port) {
- view_port_enabled_set(view_port, false);
- if(gui) {
- gui_remove_view_port(gui, view_port);
- furi_record_close("gui");
- }
- view_port_free(view_port);
- }
- infrared_last_settings_reset(last_settings);
- infrared_last_settings_free(last_settings);
- if(event_queue) {
- furi_message_queue_free(event_queue);
- }
- if(fv_priv) {
- furi_mutex_free(fv_priv->mutex);
- furi_timer_free(fv_priv->timer);
- }
- free(fv_priv);
- return ret;
- }
|