Update apps loading logic
This commit is contained in:
+140
-88
@@ -44,8 +44,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_APP_IMAGE_PATH SUNSHINE_ASSETS_DIR "/box.png"
|
#define DEFAULT_APP_IMAGE_PATH SUNSHINE_ASSETS_DIR "/box.png"
|
||||||
#define REMOTE_INPUT_UUID "8CB5C136-DA67-4F99-B4A1-F9CD35005CF4"
|
|
||||||
#define VIRTUAL_DISPLAY_UUID "8902CB19-674A-403D-A587-41B092E900BA"
|
#define VIRTUAL_DISPLAY_UUID "8902CB19-674A-403D-A587-41B092E900BA"
|
||||||
|
#define FALLBACK_DESKTOP_UUID "EAAC6159-089A-46A9-9E24-6436885F6610"
|
||||||
|
#define REMOTE_INPUT_UUID "8CB5C136-DA67-4F99-B4A1-F9CD35005CF4"
|
||||||
#define TERMINATE_APP_UUID "E16CBE1B-295D-4632-9A76-EC4180C857D3"
|
#define TERMINATE_APP_UUID "E16CBE1B-295D-4632-9A76-EC4180C857D3"
|
||||||
|
|
||||||
namespace proc {
|
namespace proc {
|
||||||
@@ -1075,14 +1076,6 @@ namespace proc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<proc::proc_t> parse(const std::string &file_name) {
|
std::optional<proc::proc_t> parse(const std::string &file_name) {
|
||||||
static uint8_t fail_count = 0;
|
|
||||||
|
|
||||||
fail_count += 1;
|
|
||||||
|
|
||||||
if (fail_count > 3) {
|
|
||||||
BOOST_LOG(warning) << "Couldn't parse/migrate apps.json properly! Apps will not be loaded."sv;
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare environment variables.
|
// Prepare environment variables.
|
||||||
auto this_env = boost::this_process::environment();
|
auto this_env = boost::this_process::environment();
|
||||||
@@ -1091,76 +1084,8 @@ namespace proc {
|
|||||||
std::vector<proc::ctx_t> apps;
|
std::vector<proc::ctx_t> apps;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (config::input.enable_input_only_mode) {
|
size_t fail_count = 0;
|
||||||
// Input Only entry
|
do {
|
||||||
{
|
|
||||||
proc::ctx_t ctx;
|
|
||||||
ctx.uuid = REMOTE_INPUT_UUID;
|
|
||||||
ctx.name = "Remote Input";
|
|
||||||
ctx.image_path = parse_env_val(this_env, "input_only.png");
|
|
||||||
ctx.virtual_display = false;
|
|
||||||
ctx.scale_factor = 100;
|
|
||||||
ctx.use_app_identity = false;
|
|
||||||
ctx.per_client_app_identity = false;
|
|
||||||
ctx.allow_client_commands = false;
|
|
||||||
|
|
||||||
ctx.elevated = false;
|
|
||||||
ctx.auto_detach = true;
|
|
||||||
ctx.wait_all = true;
|
|
||||||
ctx.exit_timeout = 5s;
|
|
||||||
|
|
||||||
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
|
||||||
if (ids.count(std::get<0>(possible_ids)) == 0) {
|
|
||||||
// Avoid using index to generate id if possible
|
|
||||||
ctx.id = std::get<0>(possible_ids);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Fallback to include index on collision
|
|
||||||
ctx.id = std::get<1>(possible_ids);
|
|
||||||
}
|
|
||||||
ids.insert(ctx.id);
|
|
||||||
|
|
||||||
input_only_app_id_str = ctx.id;
|
|
||||||
input_only_app_id = util::from_view(ctx.id);
|
|
||||||
|
|
||||||
apps.emplace_back(std::move(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate entry
|
|
||||||
{
|
|
||||||
proc::ctx_t ctx;
|
|
||||||
ctx.uuid = TERMINATE_APP_UUID;
|
|
||||||
ctx.name = "Terminate";
|
|
||||||
ctx.image_path = parse_env_val(this_env, "terminate.png");
|
|
||||||
ctx.virtual_display = false;
|
|
||||||
ctx.scale_factor = 100;
|
|
||||||
ctx.use_app_identity = false;
|
|
||||||
ctx.per_client_app_identity = false;
|
|
||||||
ctx.allow_client_commands = false;
|
|
||||||
|
|
||||||
ctx.elevated = false;
|
|
||||||
ctx.auto_detach = true;
|
|
||||||
ctx.wait_all = true;
|
|
||||||
ctx.exit_timeout = 5s;
|
|
||||||
|
|
||||||
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
|
||||||
if (ids.count(std::get<0>(possible_ids)) == 0) {
|
|
||||||
// Avoid using index to generate id if possible
|
|
||||||
ctx.id = std::get<0>(possible_ids);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Fallback to include index on collision
|
|
||||||
ctx.id = std::get<1>(possible_ids);
|
|
||||||
}
|
|
||||||
ids.insert(ctx.id);
|
|
||||||
|
|
||||||
terminate_app_id_str = ctx.id;
|
|
||||||
terminate_app_id = util::from_view(ctx.id);
|
|
||||||
|
|
||||||
apps.emplace_back(std::move(ctx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Virtual Display entry
|
// Virtual Display entry
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK) {
|
if (vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK) {
|
||||||
@@ -1176,7 +1101,7 @@ namespace proc {
|
|||||||
|
|
||||||
ctx.elevated = false;
|
ctx.elevated = false;
|
||||||
ctx.auto_detach = true;
|
ctx.auto_detach = true;
|
||||||
ctx.wait_all = true;
|
ctx.wait_all = false;
|
||||||
ctx.exit_timeout = 5s;
|
ctx.exit_timeout = 5s;
|
||||||
|
|
||||||
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
||||||
@@ -1201,7 +1126,7 @@ namespace proc {
|
|||||||
tree = nlohmann::json::parse(content);
|
tree = nlohmann::json::parse(content);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
BOOST_LOG(warning) << "Couldn't read apps.json properly! Apps will not be loaded."sv;
|
BOOST_LOG(warning) << "Couldn't read apps.json properly! Apps will not be loaded."sv;
|
||||||
return std::nullopt;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1216,7 +1141,7 @@ namespace proc {
|
|||||||
// Ensure the "apps" array exists.
|
// Ensure the "apps" array exists.
|
||||||
if (!tree.contains("apps") || !tree["apps"].is_array()) {
|
if (!tree.contains("apps") || !tree["apps"].is_array()) {
|
||||||
BOOST_LOG(warning) << "No apps were defined in apps.json!!!"sv;
|
BOOST_LOG(warning) << "No apps were defined in apps.json!!!"sv;
|
||||||
return std::nullopt;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over each application in the "apps" array.
|
// Iterate over each application in the "apps" array.
|
||||||
@@ -1302,18 +1227,137 @@ namespace proc {
|
|||||||
|
|
||||||
apps.emplace_back(std::move(ctx));
|
apps.emplace_back(std::move(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fail_count = 0;
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
BOOST_LOG(error) << "Error happened during app loading: "sv << e.what();
|
BOOST_LOG(error) << "Error happened during app loading: "sv << e.what();
|
||||||
|
|
||||||
BOOST_LOG(warning) << "App format is still invalid! Trying to re-migrate the app list..."sv;
|
|
||||||
fail_count += 1;
|
fail_count += 1;
|
||||||
tree["version"] = 0;
|
|
||||||
migrate(tree, file_name);
|
|
||||||
|
|
||||||
return parse(file_name);
|
if (fail_count >= 3) {
|
||||||
|
// No hope for recovering
|
||||||
|
BOOST_LOG(warning) << "Couldn't parse/migrate apps.json properly! Apps will not be loaded."sv;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fail_count = 0;
|
BOOST_LOG(warning) << "App format is still invalid! Trying to re-migrate the app list..."sv;
|
||||||
|
|
||||||
|
// Always try migrating from scratch when error happened
|
||||||
|
tree["version"] = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
migrate(tree, file_name);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
BOOST_LOG(error) << "Error happened during migration: "sv << e.what();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (fail_count < 3);
|
||||||
|
|
||||||
|
if (fail_count > 0) {
|
||||||
|
BOOST_LOG(warning) << "No applications configured, adding fallback Desktop entry.";
|
||||||
|
proc::ctx_t ctx;
|
||||||
|
ctx.uuid = FALLBACK_DESKTOP_UUID; // Placeholder UUID
|
||||||
|
ctx.name = "Desktop (fallback)";
|
||||||
|
ctx.image_path = parse_env_val(this_env, "desktop-alt.png");
|
||||||
|
ctx.virtual_display = false;
|
||||||
|
ctx.scale_factor = 100;
|
||||||
|
ctx.use_app_identity = false;
|
||||||
|
ctx.per_client_app_identity = false;
|
||||||
|
ctx.allow_client_commands = false;
|
||||||
|
|
||||||
|
ctx.elevated = false;
|
||||||
|
ctx.auto_detach = true;
|
||||||
|
ctx.wait_all = false; // Desktop doesn't have a specific command to wait for
|
||||||
|
ctx.exit_timeout = 5s;
|
||||||
|
|
||||||
|
// Calculate unique ID
|
||||||
|
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
||||||
|
if (ids.count(std::get<0>(possible_ids)) == 0) {
|
||||||
|
// Avoid using index to generate id if possible
|
||||||
|
ctx.id = std::get<0>(possible_ids);
|
||||||
|
} else {
|
||||||
|
// Fallback to include index on collision
|
||||||
|
ctx.id = std::get<1>(possible_ids);
|
||||||
|
}
|
||||||
|
ids.insert(ctx.id);
|
||||||
|
|
||||||
|
apps.emplace_back(std::move(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config::input.enable_input_only_mode) {
|
||||||
|
// Input Only entry
|
||||||
|
{
|
||||||
|
proc::ctx_t ctx;
|
||||||
|
ctx.uuid = REMOTE_INPUT_UUID;
|
||||||
|
ctx.name = "Remote Input";
|
||||||
|
ctx.image_path = parse_env_val(this_env, "input_only.png");
|
||||||
|
ctx.virtual_display = false;
|
||||||
|
ctx.scale_factor = 100;
|
||||||
|
ctx.use_app_identity = false;
|
||||||
|
ctx.per_client_app_identity = false;
|
||||||
|
ctx.allow_client_commands = false;
|
||||||
|
|
||||||
|
ctx.elevated = false;
|
||||||
|
ctx.auto_detach = true;
|
||||||
|
ctx.wait_all = true;
|
||||||
|
ctx.exit_timeout = 5s;
|
||||||
|
|
||||||
|
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
||||||
|
if (ids.count(std::get<0>(possible_ids)) == 0) {
|
||||||
|
// Avoid using index to generate id if possible
|
||||||
|
ctx.id = std::get<0>(possible_ids);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Fallback to include index on collision
|
||||||
|
ctx.id = std::get<1>(possible_ids);
|
||||||
|
}
|
||||||
|
ids.insert(ctx.id);
|
||||||
|
|
||||||
|
input_only_app_id_str = ctx.id;
|
||||||
|
input_only_app_id = util::from_view(ctx.id);
|
||||||
|
|
||||||
|
apps.emplace_back(std::move(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate entry
|
||||||
|
{
|
||||||
|
proc::ctx_t ctx;
|
||||||
|
ctx.uuid = TERMINATE_APP_UUID;
|
||||||
|
ctx.name = "Terminate";
|
||||||
|
ctx.image_path = parse_env_val(this_env, "terminate.png");
|
||||||
|
ctx.virtual_display = false;
|
||||||
|
ctx.scale_factor = 100;
|
||||||
|
ctx.use_app_identity = false;
|
||||||
|
ctx.per_client_app_identity = false;
|
||||||
|
ctx.allow_client_commands = false;
|
||||||
|
|
||||||
|
ctx.elevated = false;
|
||||||
|
ctx.auto_detach = true;
|
||||||
|
ctx.wait_all = true;
|
||||||
|
ctx.exit_timeout = 5s;
|
||||||
|
|
||||||
|
auto possible_ids = calculate_app_id(ctx.name, ctx.image_path, i++);
|
||||||
|
if (ids.count(std::get<0>(possible_ids)) == 0) {
|
||||||
|
// Avoid using index to generate id if possible
|
||||||
|
ctx.id = std::get<0>(possible_ids);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Fallback to include index on collision
|
||||||
|
ctx.id = std::get<1>(possible_ids);
|
||||||
|
}
|
||||||
|
ids.insert(ctx.id);
|
||||||
|
|
||||||
|
terminate_app_id_str = ctx.id;
|
||||||
|
terminate_app_id = util::from_view(ctx.id);
|
||||||
|
|
||||||
|
apps.emplace_back(std::move(ctx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return proc::proc_t {
|
return proc::proc_t {
|
||||||
std::move(this_env),
|
std::move(this_env),
|
||||||
@@ -1323,9 +1367,17 @@ namespace proc {
|
|||||||
|
|
||||||
void refresh(const std::string &file_name) {
|
void refresh(const std::string &file_name) {
|
||||||
proc.terminate();
|
proc.terminate();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (vDisplayDriverStatus != VDISPLAY::DRIVER_STATUS::OK) {
|
size_t fail_count = 0;
|
||||||
|
while (fail_count < 5 && vDisplayDriverStatus != VDISPLAY::DRIVER_STATUS::OK) {
|
||||||
initVDisplayDriver();
|
initVDisplayDriver();
|
||||||
|
if (vDisplayDriverStatus == VDISPLAY::DRIVER_STATUS::OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_count += 1;
|
||||||
|
std::this_thread::sleep_for(1s);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
"detached_cmds_desc": "A list of commands to be run in the background.",
|
"detached_cmds_desc": "A list of commands to be run in the background.",
|
||||||
"detached_cmds_note": "If the path to the command executable contains spaces, you must enclose it in quotes.",
|
"detached_cmds_note": "If the path to the command executable contains spaces, you must enclose it in quotes.",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"env_app_id": "App ID",
|
"env_app_id": "App ID (legacy)",
|
||||||
"env_app_name": "App Name",
|
"env_app_name": "App Name",
|
||||||
"env_app_uuid": "App UUID",
|
"env_app_uuid": "App UUID",
|
||||||
"env_client_audio_config": "The Audio Configuration requested by the client (2.0/5.1/7.1)",
|
"env_client_audio_config": "The Audio Configuration requested by the client (2.0/5.1/7.1)",
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
"detached_cmds_desc": "要在后台运行的命令列表。",
|
"detached_cmds_desc": "要在后台运行的命令列表。",
|
||||||
"detached_cmds_note": "如果命令可执行文件的路径包含空格,您必须在引号里将其贴出。",
|
"detached_cmds_note": "如果命令可执行文件的路径包含空格,您必须在引号里将其贴出。",
|
||||||
"edit": "编辑",
|
"edit": "编辑",
|
||||||
"env_app_id": "应用 ID",
|
"env_app_id": "应用 ID (已弃用)",
|
||||||
"env_app_name": "应用名称",
|
"env_app_name": "应用名称",
|
||||||
"env_app_uuid": "应用 UUID",
|
"env_app_uuid": "应用 UUID",
|
||||||
"env_client_audio_config": "客户端请求的音频配置 (2.0/5.1/7.1)",
|
"env_client_audio_config": "客户端请求的音频配置 (2.0/5.1/7.1)",
|
||||||
|
|||||||
Reference in New Issue
Block a user