From e53023079e2e9316507258d7a7c601c1f006b55c Mon Sep 17 00:00:00 2001 From: oxmox Date: Sun, 19 Feb 2023 12:46:17 +0100 Subject: [PATCH] ctrl: register externally started dooms that introduce themselves TODO: Check on those via kill(pid, 0) or store the last activity time in DoomState and let dooms time out if they don't send more updates. --- src/doompanning.cc | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/doompanning.cc b/src/doompanning.cc index 1a5681c..eb5891a 100644 --- a/src/doompanning.cc +++ b/src/doompanning.cc @@ -64,6 +64,7 @@ void spawn_doom(ControllerContext &ctx) // TODO: Close stdin and stdout? Leave them open for now to see the logging // output. + // FIXME: this doesn't work with SDL :( if (auto err = posix_spawn(&ds.id, DOOM_EXECUTABLE, nullptr, nullptr, const_cast(argv), nullptr)) { @@ -77,9 +78,8 @@ void spawn_doom(ControllerContext &ctx) if (!ds.texture) dp_sdl_fatal("SDL_CreateTexture"); - ctx.dooms.emplace_back(ds); - log_info("Spawned new doom, pid=%d", ds.id); + ctx.dooms.emplace_back(ds); } void end_all_dooms(ControllerContext &ctx) @@ -127,6 +127,8 @@ void check_on_dooms(ControllerContext &ctx) { pid_t pid = 0; + // This works for dooms forked from the controller, not for externally + // started dooms. do { int wstatus = 0; @@ -153,13 +155,18 @@ void check_on_dooms(ControllerContext &ctx) void do_networking(ControllerContext &ctx) { + // Set to true if we receive at least on DP_DS_Ready DoomState update. Then + // a single DP_DC_RunDoom command is broadcast. bool sendRunDoom = false; + + // Limit the max time we spend doing network stuff. + static const auto MaxNetworkingTime = std::chrono::milliseconds(10); auto tStart = std::chrono::steady_clock::now(); while (true) { if (auto elapsed = std::chrono::steady_clock::now() - tStart; - elapsed >= std::chrono::milliseconds(10)) + elapsed >= MaxNetworkingTime) { break; } @@ -179,6 +186,30 @@ void do_networking(ControllerContext &ctx) { auto msgDoomState = DP_NNG_BODY_AS(msg, MsgDoomState); + // Check if we know this doom. If it was externally started register + // it in ctx.dooms. + auto pid = msgDoomState->doomId; + auto dit = find_in_container(ctx.dooms, [pid] (const auto &ds) { return ds.id == pid; }); + + if (dit != std::end(ctx.dooms)) + { + dit->state = msgDoomState->doomState; + } + else + { + DoomState ds; + ds.id = pid; + ds.state = msgDoomState->doomState; + ds.texture = SDL_CreateTexture(ctx.renderer, SDL_PIXELFORMAT_RGB888, + SDL_TEXTUREACCESS_STREAMING, DoomScreenWidth, DoomScreenHeight); + + if (!ds.texture) + dp_sdl_fatal("SDL_CreateTexture"); + + log_info("Registered external doom, pid=%d", ds.id); + ctx.dooms.emplace_back(ds); + } + if (msgDoomState->doomState == DP_DS_Ready) sendRunDoom = true; } @@ -193,6 +224,8 @@ void do_networking(ControllerContext &ctx) auto &ds = *dit; SDL_UpdateTexture(ds.texture, nullptr, msgDoomFrame->frame, DoomFramePitch); } + else + log_warn("Received DoomFrame from unregistered doom, pid=%d", pid); } nng_msg_free(msg);