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 }