yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
application.cc
Go to the documentation of this file.
1#include "app/application.h"
2
3#include "absl/strings/str_cat.h"
4#include "util/log.h"
5
6#ifdef YAZE_WITH_GRPC
10#endif
11
12#ifdef __EMSCRIPTEN__
13#include <emscripten.h>
16#endif
17
18namespace yaze {
19
21 static Application instance;
22 return instance;
23}
24
26 config_ = config;
27 LOG_INFO("App", "Initializing Application instance...");
28
29#ifdef YAZE_WITH_GRPC
30 // Initialize gRPC server if enabled
32 LOG_INFO("App", "Initializing gRPC automation services...");
33 canvas_automation_service_ = std::make_unique<CanvasAutomationServiceImpl>();
34 grpc_server_ = std::make_unique<YazeGRPCServer>();
35
36 // Initialize server with all services
37 // Note: RomService and ProposalApprovalManager will be connected later
38 // when we have a session context, but we can start the server now.
39 auto status = grpc_server_->Initialize(
42 nullptr, // ROM not loaded yet
43 nullptr, // Version manager not ready
44 nullptr, // Approval manager not ready
45 canvas_automation_service_.get()
46 );
47
48 if (status.ok()) {
49 status = grpc_server_->StartAsync(); // Start in background thread
50 if (!status.ok()) {
51 LOG_ERROR("App", "Failed to start gRPC server: %s", std::string(status.message()).c_str());
52 } else {
53 LOG_INFO("App", "gRPC server started on port %d", config_.test_harness_port);
54 }
55 } else {
56 LOG_ERROR("App", "Failed to initialize gRPC server: %s", std::string(status.message()).c_str());
57 }
58 }
59#endif
60
61 controller_ = std::make_unique<Controller>();
62
63#ifdef YAZE_WITH_GRPC
64 // Connect services to controller/editor manager
65 if (canvas_automation_service_) {
66 controller_->SetCanvasAutomationService(canvas_automation_service_.get());
67 }
68#endif
69
70 // Process pending ROM load if we have one (from flags/config - non-WASM only)
71 std::string start_path = config_.rom_file;
72
73#ifndef __EMSCRIPTEN__
74 if (!pending_rom_.empty()) {
75 // Pending ROM takes precedence over config (e.g. drag-drop before init)
76 start_path = pending_rom_;
77 pending_rom_.clear();
78 LOG_INFO("App", "Found pending ROM load: %s", start_path.c_str());
79 } else if (!start_path.empty()) {
80 LOG_INFO("App", "Using configured startup ROM: %s", start_path.c_str());
81 } else {
82 LOG_INFO("App", "No pending ROM, starting empty.");
83 }
84#else
85 LOG_INFO("App", "WASM build - ROM loading handled via wasm_bootstrap queue.");
86 // In WASM, start_path from config might be ignored if we rely on web uploads
87 // But we can still try to pass it if it's a server-hosted ROM
88#endif
89
90 // Always call OnEntry to initialize Window/Renderer, even with empty path
91 auto status = controller_->OnEntry(start_path);
92 if (!status.ok()) {
93 LOG_ERROR("App", "Failed to initialize controller: %s", std::string(status.message()).c_str());
94 } else {
95 LOG_INFO("App", "Controller initialized successfully. Active: %s", controller_->IsActive() ? "Yes" : "No");
96
97 if (controller_->editor_manager()) {
98 controller_->editor_manager()->ApplyStartupVisibility(config_);
99 }
100
101 // If we successfully loaded a ROM at startup, run startup actions
102 if (!start_path.empty() && controller_->editor_manager()) {
104 }
105 }
106
107#ifdef __EMSCRIPTEN__
108 // Register the ROM load handler now that controller is ready.
109 yaze::app::wasm::SetRomLoadHandler([](std::string path) {
111 });
112#endif
113}
114
116 if (!controller_) return;
117
118#ifdef __EMSCRIPTEN__
119 auto& wasm_collab = app::platform::GetWasmCollaborationInstance();
120 wasm_collab.ProcessPendingChanges();
121#endif
122
123 controller_->OnInput();
124 auto status = controller_->OnLoad();
125 if (!status.ok()) {
126 LOG_ERROR("App", "Controller Load Error: %s", std::string(status.message()).c_str());
127#ifdef __EMSCRIPTEN__
128 emscripten_cancel_main_loop();
129#endif
130 return;
131 }
132
133 if (!controller_->IsActive()) {
134 // Window closed
135 // LOG_INFO("App", "Controller became inactive");
136 }
137
138 controller_->DoRender();
139}
140
141void Application::LoadRom(const std::string& path) {
142 LOG_INFO("App", "Requesting ROM load: %s", path.c_str());
143
144 if (!controller_) {
145#ifdef __EMSCRIPTEN__
146 yaze::app::wasm::TriggerRomLoad(path);
147 LOG_INFO("App", "Forwarded to wasm_bootstrap queue (controller not ready): %s", path.c_str());
148#else
149 pending_rom_ = path;
150 LOG_INFO("App", "Queued ROM load (controller not ready): %s", path.c_str());
151#endif
152 return;
153 }
154
155 // Controller exists.
156 absl::Status status;
157 if (!controller_->IsActive()) {
158 status = controller_->OnEntry(path);
159 } else {
160 status = controller_->editor_manager()->OpenRomOrProject(path);
161 }
162
163 if (!status.ok()) {
164 std::string error_msg = absl::StrCat("Failed to load ROM: ", status.message());
165 LOG_ERROR("App", "%s", error_msg.c_str());
166
167#ifdef __EMSCRIPTEN__
168 EM_ASM({
169 var msg = UTF8ToString($0);
170 console.error(msg);
171 alert(msg);
172 }, error_msg.c_str());
173#endif
174 } else {
175 LOG_INFO("App", "ROM loaded successfully: %s", path.c_str());
176
177 // Run startup actions whenever a new ROM is loaded IF it matches our startup config
178 // (Optional: we might only want to run actions once at startup, but for CLI usage usually
179 // you load one ROM and want the actions applied to it).
180 // For now, we'll only run actions if this is the first load or if explicitly requested.
181 // Actually, simpler: just run them. The user can close cards if they want.
183
184#ifdef __EMSCRIPTEN__
185 EM_ASM({
186 console.log("ROM loaded successfully: " + UTF8ToString($0));
187 }, path.c_str());
188#endif
189 }
190}
191
193 if (!controller_ || !controller_->editor_manager()) return;
194
195 auto* manager = controller_->editor_manager();
196 manager->ProcessStartupActions(config_);
197}
198
199#ifdef __EMSCRIPTEN__
200extern "C" void SyncFilesystem();
201#endif
202
204#ifdef __EMSCRIPTEN__
205 // Sync IDBFS to persist any changes before shutdown
206 LOG_INFO("App", "Syncing filesystem before shutdown...");
207 SyncFilesystem();
208#endif
209
210#ifdef YAZE_WITH_GRPC
211 if (grpc_server_) {
212 LOG_INFO("App", "Shutting down gRPC server...");
213 grpc_server_->Shutdown();
214 grpc_server_.reset();
215 }
216 canvas_automation_service_.reset();
217#endif
218
219 if (controller_) {
220 controller_->OnExit();
221 controller_.reset();
222 }
223}
224
225} // namespace yaze
Main application singleton managing lifecycle and global state.
Definition application.h:52
std::string pending_rom_
Definition application.h:90
AppConfig config_
Definition application.h:85
static Application & Instance()
std::unique_ptr< Controller > controller_
Definition application.h:84
void LoadRom(const std::string &path)
static TestManager & Get()
#define LOG_ERROR(category, format,...)
Definition log.h:109
#define LOG_INFO(category, format,...)
Definition log.h:105
Configuration options for the application startup.
Definition application.h:23
std::string rom_file
Definition application.h:25
bool enable_test_harness
Definition application.h:44