watchdog: return to main menu and reset config after inactivity in kiosk mode

This commit is contained in:
Andrei Alexeyev 2024-05-04 12:47:00 +02:00 committed by Andrei Alexeyev
parent 0b2280b7ed
commit 858398f556
No known key found for this signature in database
GPG key ID: 72D26128040B9690
9 changed files with 172 additions and 4 deletions

View file

@ -23,6 +23,7 @@
#include "video.h"
#include "eventloop/eventloop.h"
#include "replay/demoplayer.h"
#include "watchdog.h"
#define SKIP_DELAY 3
#define AUTO_ADVANCE_TIME_BEFORE_TEXT FPS * 2
@ -30,7 +31,10 @@
#define AUTO_ADVANCE_TIME_CROSS_SCENE FPS * 180
// TODO maybe make transitions configurable?
#define CUTSCENE_FADE_OUT 200
enum {
CUTSCENE_FADE_OUT = 200,
CUTSCENE_INTERRUPT_FADE_OUT = 15,
};
typedef struct CutsceneBGState {
Texture *scene;
@ -118,8 +122,12 @@ static bool skip_text_animation(CutsceneState *st) {
return animation_skipped;
}
static void begin_fadeout(CutsceneState *st) {
const int fade_frames = CUTSCENE_FADE_OUT;
static void begin_fadeout(CutsceneState *st, int fade_frames) {
if(st->fadeout_timer) {
log_debug("Already fading out, timer = %i", st->fadeout_timer);
return;
}
audio_bgm_stop((FPS * fade_frames) / 4000.0);
set_transition(TransFadeBlack, fade_frames, fade_frames, NO_CALLCHAIN);
st->fadeout_timer = fade_frames;
@ -148,7 +156,7 @@ static void cutscene_advance(CutsceneState *st) {
if((++st->phase)->background == NULL) {
st->phase = NULL;
begin_fadeout(st);
begin_fadeout(st, CUTSCENE_FADE_OUT);
} else {
switch_bg(st, st->phase->background);
}
@ -166,6 +174,10 @@ static void cutscene_advance(CutsceneState *st) {
reset_timers(st);
}
static void cutscene_interrupt(CutsceneState *st) {
begin_fadeout(st, CUTSCENE_INTERRUPT_FADE_OUT);
}
static bool cutscene_event(SDL_Event *evt, void *ctx) {
CutsceneState *st = ctx;
@ -179,6 +191,10 @@ static bool cutscene_event(SDL_Event *evt, void *ctx) {
static LogicFrameAction cutscene_logic_frame(void *ctx) {
CutsceneState *st = ctx;
if(watchdog_signaled()) {
cutscene_interrupt(st);
}
update_transition();
events_poll((EventHandler[]) {
{ .proc = cutscene_event, .arg = st, .priority = EPRIO_NORMAL },

View file

@ -50,6 +50,8 @@ typedef enum {
TE_FILEWATCH,
TE_WATCHDOG,
NUM_TAISEI_EVENTS
} TaiseiEvent;

View file

@ -35,6 +35,13 @@
#include "eventloop/eventloop.h"
#include "replay/demoplayer.h"
#include "replay/tsrtool.h"
#include "watchdog.h"
static bool watchdog_handler(SDL_Event *evt, void *arg) {
assert(evt->type == MAKE_TAISEI_EVENT(TE_WATCHDOG));
config_reset();
return true;
}
attr_unused
static void taisei_shutdown(void) {
@ -48,6 +55,11 @@ static void taisei_shutdown(void) {
r_release_resources();
res_shutdown();
if(global.is_kiosk_mode) {
events_unregister_handler(watchdog_handler);
}
watchdog_shutdown();
demoplayer_shutdown();
progress_unload();
stage_objpools_shutdown();
@ -380,6 +392,16 @@ static void main_post_vfsinit(CallChainResult ccr) {
time_init();
init_global(&ctx->cli);
events_init();
if(global.is_kiosk_mode) {
watchdog_init(env_get("TAISEI_KIOSK_TIMEOUT", 60 * FPS));
events_register_handler(&(EventHandler) {
.priority = EPRIO_SYSTEM,
.event_type = MAKE_TAISEI_EVENT(TE_WATCHDOG),
.proc = watchdog_handler,
});
}
video_init(&(VideoInitParams) {
.width = ctx->cli.width,
.height = ctx->cli.height,

View file

@ -24,6 +24,7 @@
#include "stage.h"
#include "version.h"
#include "plrmodes.h"
#include "watchdog.h"
static MenuEntry *spell_practice_entry;
static MenuEntry *stage_practice_entry;
@ -65,6 +66,12 @@ static void begin_main_menu(MenuData *m) {
}
static void update_main_menu(MenuData *menu) {
if(watchdog_signaled()) {
menu->cursor = 0;
}
watchdog_reset();
menu->drawdata[1] += 0.1*(menu->cursor-menu->drawdata[1]);
dynarray_foreach(&menu->entries, int i, MenuEntry *e, {

View file

@ -14,6 +14,7 @@
#include "eventloop/eventloop.h"
#include "replay/demoplayer.h"
#include "util/graphics.h"
#include "watchdog.h"
MenuEntry *add_menu_entry(MenuData *menu, const char *name, MenuAction action, void *arg) {
return dynarray_append(&menu->entries, {
@ -201,6 +202,11 @@ static LogicFrameAction menu_logic_frame(void *arg) {
menu->frames++;
if(watchdog_signaled()) {
menu->selected = -1;
close_menu(menu);
}
if(menu->state != MS_FadeOut || menu->flags & MF_AlwaysProcessInput) {
assert(menu->input);
menu->input(menu);

View file

@ -100,6 +100,7 @@ taisei_src = files(
'version.c',
'video.c',
'video_postprocess.c',
'watchdog.c',
)
if is_developer_build

View file

@ -30,6 +30,7 @@
#include "common_tasks.h"
#include "stageinfo.h"
#include "dynstage.h"
#include "watchdog.h"
typedef struct StageFrameState {
StageInfo *stage;
@ -948,6 +949,10 @@ static LogicFrameAction stage_logic_frame(void *arg) {
stage_update_fps(fstate);
if(watchdog_signaled() && !stage_is_demo_mode()) {
global.gameover = GAMEOVER_ABORT;
}
if(stage_is_skip_mode()) {
global.plr.iddqd = true;
}

93
src/watchdog.c Normal file
View file

@ -0,0 +1,93 @@
/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "events.h"
#include "log.h"
#include "watchdog.h"
static struct {
int countdown;
int timeout;
} watchdog;
static inline bool watchdog_initialized(void) {
return watchdog.timeout;
}
static void watchdog_tick(void) {
assert(watchdog_initialized());
if(watchdog.countdown > 0) {
if(--watchdog.countdown == 0) {
log_info("Watchdog signaled");
events_emit(TE_WATCHDOG, 0, NULL, NULL);
}
}
}
static bool watchdog_event(SDL_Event *event, void *arg) {
assert(watchdog_initialized());
switch(event->type) {
case SDL_KEYDOWN:
watchdog_reset();
return false;
default: switch(TAISEI_EVENT(event->type)) {
case TE_GAMEPAD_BUTTON_DOWN:
case TE_GAMEPAD_AXIS_DIGITAL:
watchdog_reset();
return false;
case TE_FRAME:
watchdog_tick();
return false;
}
}
return false;
}
void watchdog_init(int timeout) {
if(timeout <= 0) {
return;
}
assert(!watchdog_initialized());
events_register_handler(&(EventHandler) {
.priority = EPRIO_SYSTEM,
.proc = watchdog_event,
});
watchdog.timeout = timeout;
watchdog_reset();
}
void watchdog_shutdown(void) {
if(watchdog_initialized()) {
events_unregister_handler(watchdog_event);
watchdog.timeout = 0;
}
}
bool watchdog_signaled(void) {
return watchdog_initialized() && watchdog.countdown == 0;
}
void watchdog_reset(void) {
if(watchdog_initialized()) {
watchdog.countdown = watchdog.timeout;
}
}
void watchdog_suspend(void) {
if(watchdog_initialized()) {
watchdog.countdown = -1;
}
}

16
src/watchdog.h Normal file
View file

@ -0,0 +1,16 @@
/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#pragma once
#include "taisei.h"
void watchdog_init(int timeout);
void watchdog_shutdown(void);
bool watchdog_signaled(void);
void watchdog_reset(void);
void watchdog_suspend(void);