Add simulator mode with app discovery and mosis.apps API
Simulator mode (--simulator flag): - Starts from main home.rml instead of separate simulator home - Discovers apps from test-apps folder automatically - Shows discovered apps in home screen grid mosis.apps API for Lua: - getInstalled() returns array of discovered apps - launch(package_id) starts an app with its own sandbox goHome improvements: - Uses g_main_assets_path to find home.rml correctly - Works when running test apps directly - Properly clears current app state Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,7 @@ static std::ofstream g_log_file;
|
||||
static bool g_simulator_mode = false;
|
||||
static std::string g_test_apps_path; // Path to test-apps directory
|
||||
static std::string g_simulator_home_path; // Path to simulator home.rml
|
||||
static std::string g_main_assets_path; // Path to main assets (for goHome)
|
||||
static std::vector<mosis::AppInfo> g_discovered_apps;
|
||||
static std::string g_current_app_id; // Currently running app (empty = home)
|
||||
|
||||
@@ -364,27 +365,31 @@ int main(int argc, char* argv[]) {
|
||||
g_test_apps_path = fs::absolute(g_test_apps_path).string();
|
||||
}
|
||||
|
||||
// Simulator home screen path
|
||||
std::vector<std::string> sim_search_paths = {
|
||||
"simulator/home.rml",
|
||||
"../designer/assets/simulator/home.rml",
|
||||
fs::absolute("simulator/home.rml").string(),
|
||||
// Find main assets home.rml for simulator mode
|
||||
// Look for src/main/assets/apps/home/home.rml relative to test-apps
|
||||
fs::path test_apps_fs = fs::path(g_test_apps_path);
|
||||
std::vector<fs::path> home_search_paths = {
|
||||
test_apps_fs.parent_path() / "src" / "main" / "assets" / "apps" / "home" / "home.rml",
|
||||
fs::path("src/main/assets/apps/home/home.rml"),
|
||||
fs::absolute("src/main/assets/apps/home/home.rml"),
|
||||
};
|
||||
for (const auto& path : sim_search_paths) {
|
||||
for (const auto& path : home_search_paths) {
|
||||
if (fs::exists(path)) {
|
||||
g_simulator_home_path = fs::absolute(path).string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Override document path to simulator home
|
||||
// Override document path to main home screen
|
||||
if (!g_simulator_home_path.empty()) {
|
||||
document_path = g_simulator_home_path;
|
||||
// Also set the main assets path for proper resource loading
|
||||
g_main_assets_path = fs::path(g_simulator_home_path).parent_path().parent_path().parent_path().string();
|
||||
std::cout << "Simulator mode enabled" << std::endl;
|
||||
std::cout << "Test apps path: " << g_test_apps_path << std::endl;
|
||||
std::cout << "Simulator home: " << g_simulator_home_path << std::endl;
|
||||
std::cout << "Home screen: " << g_simulator_home_path << std::endl;
|
||||
} else {
|
||||
std::cerr << "Warning: Could not find simulator home.rml" << std::endl;
|
||||
std::cerr << "Warning: Could not find home.rml for simulator" << std::endl;
|
||||
g_simulator_mode = false;
|
||||
}
|
||||
}
|
||||
@@ -453,6 +458,26 @@ int main(int argc, char* argv[]) {
|
||||
// Make assets_path absolute
|
||||
assets_path = fs::absolute(assets_path).string();
|
||||
std::cout << "Assets path: " << assets_path << std::endl;
|
||||
|
||||
// Determine main assets path (where home.rml lives)
|
||||
// This is important for goHome() when running test apps
|
||||
g_main_assets_path = assets_path;
|
||||
|
||||
// Check if we're running from test-apps folder
|
||||
fs::path assets_fs = fs::path(assets_path);
|
||||
if (assets_fs.filename().string().find("com.") == 0 ||
|
||||
assets_fs.parent_path().filename() == "test-apps") {
|
||||
// Running a test app - find the main assets
|
||||
fs::path test_apps_root = assets_fs.parent_path();
|
||||
if (test_apps_root.filename() != "test-apps") {
|
||||
test_apps_root = test_apps_root.parent_path();
|
||||
}
|
||||
fs::path main_assets = test_apps_root.parent_path() / "src" / "main" / "assets";
|
||||
if (fs::exists(main_assets / "apps" / "home" / "home.rml")) {
|
||||
g_main_assets_path = main_assets.string();
|
||||
std::cout << "Main assets: " << g_main_assets_path << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << "Resolution: " << g_width << "x" << g_height << std::endl;
|
||||
|
||||
// Print mode info
|
||||
@@ -775,7 +800,46 @@ bool InitializeRmlUi(const std::string& assets_path, int fb_width, int fb_height
|
||||
return 1;
|
||||
});
|
||||
lua_setglobal(L, "loadScreen");
|
||||
std::cout << "Registered Lua loadScreen function" << std::endl;
|
||||
|
||||
// Register goHome function to return to home screen
|
||||
lua_pushcfunction(L, [](lua_State* L) -> int {
|
||||
if (!g_context) {
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "goHome called - returning to home screen" << std::endl;
|
||||
|
||||
// Close existing documents (except debugger)
|
||||
while (g_context->GetNumDocuments() > 1) {
|
||||
auto* doc = g_context->GetDocument(0);
|
||||
if (doc && doc->GetSourceURL().find("__rmlui") == std::string::npos) {
|
||||
doc->Close();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load home screen from main assets path
|
||||
std::string home_path = (fs::path(g_main_assets_path) / "apps" / "home" / "home.rml").string();
|
||||
std::cout << "Loading home from: " << home_path << std::endl;
|
||||
|
||||
auto* document = g_context->LoadDocument(home_path);
|
||||
if (document) {
|
||||
document->Show();
|
||||
g_current_document_path = home_path;
|
||||
g_current_screen_url = home_path;
|
||||
g_current_app_id = ""; // Clear current app
|
||||
Rml::Log::Message(Rml::Log::LT_INFO, "Returned to home screen");
|
||||
lua_pushboolean(L, true);
|
||||
} else {
|
||||
Rml::Log::Message(Rml::Log::LT_ERROR, "Failed to load home screen from: %s", home_path.c_str());
|
||||
lua_pushboolean(L, false);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
lua_setglobal(L, "goHome");
|
||||
std::cout << "Registered Lua loadScreen and goHome functions" << std::endl;
|
||||
|
||||
// Register simulator API (if in simulator mode)
|
||||
if (g_simulator_mode) {
|
||||
@@ -938,6 +1002,93 @@ bool InitializeRmlUi(const std::string& assets_path, int fb_width, int fb_height
|
||||
|
||||
lua_setglobal(L, "simulator");
|
||||
std::cout << "Registered simulator Lua API" << std::endl;
|
||||
|
||||
// Also register mosis.apps API for compatibility with home.lua
|
||||
// Create mosis table (or get existing)
|
||||
lua_getglobal(L, "mosis");
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
}
|
||||
|
||||
// Create mosis.apps table
|
||||
lua_newtable(L);
|
||||
|
||||
// mosis.apps.getInstalled() - returns installed apps
|
||||
lua_pushcfunction(L, [](lua_State* L) -> int {
|
||||
// Discover apps if not already done
|
||||
if (g_discovered_apps.empty() && !g_test_apps_path.empty()) {
|
||||
g_discovered_apps = mosis::AppDiscovery::DiscoverApps(g_test_apps_path);
|
||||
std::cout << "Discovered " << g_discovered_apps.size() << " apps in " << g_test_apps_path << std::endl;
|
||||
}
|
||||
|
||||
// Create apps table (array format expected by home.lua)
|
||||
lua_newtable(L);
|
||||
int app_index = 1;
|
||||
for (const auto& app : g_discovered_apps) {
|
||||
lua_pushinteger(L, app_index++);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushstring(L, app.name.c_str());
|
||||
lua_setfield(L, -2, "name");
|
||||
|
||||
lua_pushstring(L, app.id.c_str());
|
||||
lua_setfield(L, -2, "package_id");
|
||||
|
||||
lua_pushstring(L, app.GetIconPath().c_str());
|
||||
lua_setfield(L, -2, "icon");
|
||||
|
||||
lua_pushboolean(L, false); // Not a system app
|
||||
lua_setfield(L, -2, "is_system_app");
|
||||
|
||||
lua_pushstring(L, app.app_path.c_str());
|
||||
lua_setfield(L, -2, "install_path");
|
||||
|
||||
lua_pushstring(L, app.entry.c_str());
|
||||
lua_setfield(L, -2, "entry_point");
|
||||
|
||||
lua_settable(L, -3); // apps[index] = app_table
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
lua_setfield(L, -2, "getInstalled");
|
||||
|
||||
// mosis.apps.launch(package_id) - launch an app
|
||||
lua_pushcfunction(L, [](lua_State* L) -> int {
|
||||
const char* package_id = luaL_checkstring(L, 1);
|
||||
|
||||
// Find the app
|
||||
for (const auto& app : g_discovered_apps) {
|
||||
if (app.id == package_id) {
|
||||
std::cout << "mosis.apps.launch: Starting " << package_id << std::endl;
|
||||
g_current_app_id = package_id;
|
||||
|
||||
// Reset sandbox for the new app
|
||||
if (g_sandbox) {
|
||||
g_sandbox->UnregisterAPIs(L);
|
||||
g_sandbox->Reset();
|
||||
|
||||
mosis::DesktopSandboxConfig config;
|
||||
config.app_id = package_id;
|
||||
config.data_root = app.app_path + "/sandbox_data";
|
||||
g_sandbox = std::make_unique<mosis::DesktopSandbox>(config);
|
||||
g_sandbox->RegisterAPIs(L);
|
||||
}
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "mosis.apps.launch: App not found: " << package_id << std::endl;
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
});
|
||||
lua_setfield(L, -2, "launch");
|
||||
|
||||
lua_setfield(L, -2, "apps"); // mosis.apps = apps_table
|
||||
lua_setglobal(L, "mosis");
|
||||
std::cout << "Registered mosis.apps Lua API" << std::endl;
|
||||
}
|
||||
|
||||
// Load fonts - search for fonts directory in multiple locations
|
||||
|
||||
Reference in New Issue
Block a user