URI:
       scene_timer_running.c - timed-remote - Flipper Zero app for sending delayed IR commands
  HTML git clone git://src.adamsgaard.dk/timed-remote
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       scene_timer_running.c (3424B)
       ---
            1 #include <stdio.h>
            2 
            3 #include "../helpers/ir_helper.h"
            4 #include "../helpers/time_helper.h"
            5 #include "../timed_remote.h"
            6 #include "timed_remote_scene.h"
            7 
            8 static uint32_t        countdown_seconds(const TimedRemoteApp *);
            9 static void        render_timer(TimedRemoteApp *);
           10 
           11 #define REPEAT_UNLIMITED 255U
           12 
           13 static void
           14 on_timer_tick(void *context)
           15 {
           16         TimedRemoteApp *app;
           17 
           18         app = context;
           19         view_dispatcher_send_custom_event(app->vd, EVENT_TIMER_TICK);
           20 }
           21 
           22 static uint32_t
           23 countdown_seconds(const TimedRemoteApp *app)
           24 {
           25         return time_hms_sec(app->h, app->m, app->s);
           26 }
           27 
           28 static void
           29 render_timer(TimedRemoteApp *app)
           30 {
           31         char timer[16];
           32         uint8_t h;
           33         uint8_t m;
           34         uint8_t s;
           35 
           36         time_sec_hms(app->left, &h, &m, &s);
           37         snprintf(timer, sizeof(timer), "%02d:%02d:%02d", h, m, s);
           38 
           39         widget_reset(app->widget);
           40         widget_add_string_element(
           41             app->widget,
           42             64,
           43             5,
           44             AlignCenter,
           45             AlignTop,
           46             FontSecondary,
           47             app->sig);
           48         widget_add_string_element(
           49             app->widget,
           50             64,
           51             25,
           52             AlignCenter,
           53             AlignTop,
           54             FontBigNumbers,
           55             timer);
           56 
           57         if (app->repeat > 0 && app->repeat < REPEAT_UNLIMITED) {
           58                 char repeat[24];
           59 
           60                 snprintf(
           61                     repeat,
           62                     sizeof(repeat),
           63                     "Repeat: %d/%d",
           64                     app->repeat - app->repeat_left + 1,
           65                     app->repeat);
           66                 widget_add_string_element(
           67                     app->widget,
           68                     64,
           69                     52,
           70                     AlignCenter,
           71                     AlignTop,
           72                     FontSecondary,
           73                     repeat);
           74         } else if (app->repeat == REPEAT_UNLIMITED) {
           75                 widget_add_string_element(
           76                     app->widget,
           77                     64,
           78                     52,
           79                     AlignCenter,
           80                     AlignTop,
           81                     FontSecondary,
           82                     "Repeat: Unlimited");
           83         }
           84 }
           85 
           86 void
           87 scene_run_enter(void *context)
           88 {
           89         TimedRemoteApp *app;
           90 
           91         app = context;
           92         if (app->mode == MODE_COUNTDOWN) {
           93                 app->left = countdown_seconds(app);
           94         } else {
           95                 app->left = time_until(app->h, app->m, app->s);
           96                 if (app->left == 0) {
           97                         view_dispatcher_send_custom_event(app->vd, EVENT_FIRE_SIGNAL);
           98                         return;
           99                 }
          100         }
          101 
          102         if (app->repeat == 0)
          103                 app->repeat_left = 1;
          104 
          105         render_timer(app);
          106         view_dispatcher_switch_to_view(app->vd, VIEW_RUN);
          107 
          108         app->timer = furi_timer_alloc(on_timer_tick, FuriTimerTypePeriodic, app);
          109         if (app->timer == NULL)
          110                 return;
          111 
          112         furi_timer_start(app->timer, furi_kernel_get_tick_frequency());
          113 }
          114 
          115 bool
          116 scene_run_event(void *context, SceneManagerEvent event)
          117 {
          118         TimedRemoteApp *app;
          119 
          120         app = context;
          121         if (event.type == SceneManagerEventTypeBack) {
          122                 scene_manager_search_and_switch_to_previous_scene(
          123                     app->sm,
          124                     SCENE_BROWSE);
          125                 return true;
          126         }
          127         if (event.type != SceneManagerEventTypeCustom)
          128                 return false;
          129 
          130         if (event.event == EVENT_TIMER_TICK) {
          131                 if (app->left > 0) {
          132                         app->left--;
          133                         render_timer(app);
          134                 }
          135                 if (app->left == 0)
          136                         view_dispatcher_send_custom_event(app->vd, EVENT_FIRE_SIGNAL);
          137                 return true;
          138         }
          139         if (event.event != EVENT_FIRE_SIGNAL)
          140                 return false;
          141 
          142         if (app->ir != NULL)
          143                 ir_tx(app->ir);
          144 
          145         if (app->repeat == REPEAT_UNLIMITED) {
          146                 app->left = countdown_seconds(app);
          147                 render_timer(app);
          148                 return true;
          149         }
          150 
          151         if (app->repeat_left > 0)
          152                 app->repeat_left--;
          153 
          154         if (app->repeat != 0 && app->repeat_left > 0) {
          155                 app->left = countdown_seconds(app);
          156                 render_timer(app);
          157                 return true;
          158         }
          159 
          160         scene_manager_next_scene(app->sm, SCENE_DONE);
          161         return true;
          162 }
          163 
          164 void
          165 scene_run_exit(void *context)
          166 {
          167         TimedRemoteApp *app;
          168 
          169         app = context;
          170         if (app->timer != NULL) {
          171                 furi_timer_stop(app->timer);
          172                 furi_timer_free(app->timer);
          173                 app->timer = NULL;
          174         }
          175         widget_reset(app->widget);
          176 }