diff --git a/include/tasks.hpp b/include/tasks.hpp index 19be79d..0e9be9d 100644 --- a/include/tasks.hpp +++ b/include/tasks.hpp @@ -38,48 +38,85 @@ namespace nxdt::tasks typedef brls::VoidEvent VoidEvent; typedef brls::Event BooleanEvent; + /* Custom vector type used to hold pointers to application metadata entries. */ + typedef std::vector TitleApplicationMetadataVector; + + /* Custom vector type used to hold UMS devices. */ + typedef std::vector UmsDeviceVector; + /* Gamecard task. */ class GameCardTask: public brls::RepeatingTask { private: + GameCardStatusEvent gc_status_event; + GameCardStatus cur_gc_status = GameCardStatus_NotInserted; GameCardStatus prev_gc_status = GameCardStatus_NotInserted; - GameCardStatusEvent *gc_status_event = nullptr; public: - GameCardTask(GameCardStatusEvent *gc_status_event); + GameCardTask(void); + ~GameCardTask(void); + void run(retro_time_t current_time) override; + + GameCardStatusEvent* GetTaskEvent(void); }; - /* Gamecard title task. */ - class GameCardTitleTask: public brls::RepeatingTask + /* Title task. */ + class TitleTask: public brls::RepeatingTask { private: - VoidEvent *gc_title_event = nullptr; + VoidEvent title_event; + + TitleApplicationMetadataVector system_metadata; + TitleApplicationMetadataVector user_metadata; + + void PopulateApplicationMetadataVector(bool is_system); public: - GameCardTitleTask(VoidEvent *gc_title_event); + TitleTask(void); + ~TitleTask(void); + void run(retro_time_t current_time) override; + + VoidEvent* GetTaskEvent(void); + + TitleApplicationMetadataVector* GetApplicationMetadata(bool is_system); }; /* USB Mass Storage task. */ class UmsTask: public brls::RepeatingTask { private: - VoidEvent *ums_event = nullptr; + VoidEvent ums_event; + + UmsDeviceVector ums_devices; + + void PopulateUmsDeviceVector(void); public: - UmsTask(VoidEvent *ums_event); + UmsTask(void); + ~UmsTask(void); + void run(retro_time_t current_time) override; + + VoidEvent* GetTaskEvent(void); + + UmsDeviceVector* GetUmsDevices(void); }; /* USB host device connection task. */ class UsbHostTask: public brls::RepeatingTask { private: + BooleanEvent usb_host_event; + bool cur_usb_host_status = false; bool prev_usb_host_status = false; - BooleanEvent *usb_host_event = nullptr; public: - UsbHostTask(BooleanEvent *usb_host_event); + UsbHostTask(void); + ~UsbHostTask(void); + void run(retro_time_t current_time) override; + + BooleanEvent* GetTaskEvent(void); }; } diff --git a/source/main.cpp b/source/main.cpp index 214ba3e..28f1f44 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -44,6 +44,11 @@ std::vector NOTIFICATIONS = { "Hmm, Steamed Hams!" }; +nxdt::tasks::GameCardTask *gc_task = nullptr; +nxdt::tasks::TitleTask *title_task = nullptr; +nxdt::tasks::UmsTask *ums_task = nullptr; +nxdt::tasks::UsbHostTask *usb_host_task = nullptr; + int main(int argc, char* argv[]) { ON_SCOPE_EXIT { utilsCloseResources(); }; @@ -60,34 +65,17 @@ int main(int argc, char* argv[]) /* Initialize Borealis. */ if (!brls::Application::init(APP_TITLE)) return EXIT_FAILURE; + /* Start background tasks. */ + gc_task = new nxdt::tasks::GameCardTask(); + title_task = new nxdt::tasks::TitleTask(); + ums_task = new nxdt::tasks::UmsTask(); + usb_host_task = new nxdt::tasks::UsbHostTask(); + /* Create root tab frame. */ brls::TabFrame *root_frame = new brls::TabFrame(); root_frame->setTitle(APP_TITLE); root_frame->setIcon(BOREALIS_ASSET("icon/" APP_TITLE ".jpg")); root_frame->setFooterText("v" APP_VERSION); - - /* Create and start gamecard task. */ - nxdt::tasks::GameCardStatusEvent gc_status_event; - nxdt::tasks::GameCardTask *gc_task = new nxdt::tasks::GameCardTask(&gc_status_event); - gc_task->start(); - - /* Create and start gamecard title task. */ - nxdt::tasks::VoidEvent gc_title_event; - nxdt::tasks::GameCardTitleTask *gc_title_task = new nxdt::tasks::GameCardTitleTask(&gc_title_event); - gc_title_task->start(); - - /* Create and start UMS task. */ - nxdt::tasks::VoidEvent ums_event; - nxdt::tasks::UmsTask *ums_task = new nxdt::tasks::UmsTask(&ums_event); - ums_task->start(); - - /* Create and start USB host task. */ - nxdt::tasks::BooleanEvent usb_host_event; - nxdt::tasks::UsbHostTask *usb_host_task = new nxdt::tasks::UsbHostTask(&usb_host_event); - usb_host_task->start(); - - - diff --git a/source/tasks.cpp b/source/tasks.cpp index fd83bd0..e6d1a8f 100644 --- a/source/tasks.cpp +++ b/source/tasks.cpp @@ -22,15 +22,21 @@ #include #include -#define TASK_INTERVAL 100 /* 100 ms. */ +#define NXDT_TASK_INTERVAL 100 /* 100 ms. */ namespace nxdt::tasks { /* Gamecard task. */ - GameCardTask::GameCardTask(GameCardStatusEvent *gc_status_event) : brls::RepeatingTask(TASK_INTERVAL) + GameCardTask::GameCardTask(void) : brls::RepeatingTask(NXDT_TASK_INTERVAL) { - this->gc_status_event = gc_status_event; + brls::RepeatingTask::start(); + brls::Logger::debug("Gamecard task started."); + } + + GameCardTask::~GameCardTask(void) + { + brls::Logger::debug("Gamecard task stopped."); } void GameCardTask::run(retro_time_t current_time) @@ -40,35 +46,123 @@ namespace nxdt::tasks this->cur_gc_status = (GameCardStatus)gamecardGetStatus(); if (this->cur_gc_status != this->prev_gc_status) { - this->gc_status_event->fire(this->cur_gc_status); + this->gc_status_event.fire(this->cur_gc_status); this->prev_gc_status = this->cur_gc_status; brls::Logger::debug("Gamecard status change triggered: {}.", this->cur_gc_status); } } - /* Gamecard title task. */ - - GameCardTitleTask::GameCardTitleTask(VoidEvent *gc_title_event) : brls::RepeatingTask(TASK_INTERVAL) + GameCardStatusEvent* GameCardTask::GetTaskEvent(void) { - this->gc_title_event = gc_title_event; + return &(this->gc_status_event); } - void GameCardTitleTask::run(retro_time_t current_time) + /* Title task. */ + + TitleTask::TitleTask(void) : brls::RepeatingTask(NXDT_TASK_INTERVAL) + { + /* Get system metadata entries. */ + this->PopulateApplicationMetadataVector(true); + + /* Get user metadata entries. */ + this->PopulateApplicationMetadataVector(false); + + /* Start task. */ + brls::RepeatingTask::start(); + brls::Logger::debug("Title task started."); + } + + TitleTask::~TitleTask(void) + { + /* Clear application metadata vectors. */ + this->system_metadata.clear(); + this->user_metadata.clear(); + + brls::Logger::debug("Title task stopped."); + } + + void TitleTask::PopulateApplicationMetadataVector(bool is_system) + { + TitleApplicationMetadata **app_metadata = NULL; + u32 app_metadata_count = 0; + + /* Get pointer to output vector. */ + TitleApplicationMetadataVector *vector = (is_system ? &(this->system_metadata) : &(this->user_metadata)); + if (vector->size()) vector->clear(); + + /* Get application metadata entries. */ + app_metadata = titleGetApplicationMetadataEntries(is_system, &app_metadata_count); + if (!app_metadata) return; + + /* Fill output vector. */ + for(u32 i = 0; i < app_metadata_count; i++) vector->push_back(app_metadata[i]); + + /* Free application metadata array. */ + free(app_metadata); + + brls::Logger::debug("Retrieved {} {} metadata {}.", app_metadata_count, is_system ? "system" : "user", app_metadata_count == 1 ? "entry" : "entries"); + } + + void TitleTask::run(retro_time_t current_time) { brls::RepeatingTask::run(current_time); if (titleIsGameCardInfoUpdated()) { - this->gc_title_event->fire(); - brls::Logger::debug("Gamecard title info updated."); + /* Update user metadata vector. */ + this->PopulateApplicationMetadataVector(false); + + /* Fire task event. */ + this->title_event.fire(); + brls::Logger::debug("Title info updated."); } } + VoidEvent* TitleTask::GetTaskEvent(void) + { + return &(this->title_event); + } + + TitleApplicationMetadataVector* TitleTask::GetApplicationMetadata(bool is_system) + { + return (is_system ? &(this->system_metadata) : &(this->user_metadata)); + } + /* USB Mass Storage task. */ - UmsTask::UmsTask(VoidEvent *ums_event) : brls::RepeatingTask(TASK_INTERVAL) + UmsTask::UmsTask(void) : brls::RepeatingTask(NXDT_TASK_INTERVAL) { - this->ums_event = ums_event; + brls::RepeatingTask::start(); + brls::Logger::debug("UMS task started."); + } + + UmsTask::~UmsTask(void) + { + /* Clear UMS device vector. */ + this->ums_devices.clear(); + + brls::Logger::debug("UMS task stopped."); + } + + void UmsTask::PopulateUmsDeviceVector(void) + { + UsbHsFsDevice *ums_devices = NULL; + u32 ums_device_count = 0; + + /* Clear UMS device vector (if needed). */ + if (this->ums_devices.size()) this->ums_devices.clear(); + + /* Get UMS devices. */ + ums_devices = umsGetDevices(&ums_device_count); + if (!ums_devices) return; + + /* Fill UMS device vector. */ + for(u32 i = 0; i < ums_device_count; i++) this->ums_devices.push_back(ums_devices[i]); + + /* Free UMS devices array. */ + free(ums_devices); + + brls::Logger::debug("Retrieved info for {} UMS {}.", ums_device_count, ums_device_count == 1 ? "device" : "devices"); } void UmsTask::run(retro_time_t current_time) @@ -77,16 +171,36 @@ namespace nxdt::tasks if (umsIsDeviceInfoUpdated()) { - this->ums_event->fire(); + /* Update UMS device vector. */ + this->PopulateUmsDeviceVector(); + + /* Fire task event. */ + this->ums_event.fire(); brls::Logger::debug("UMS device info updated."); } } + VoidEvent* UmsTask::GetTaskEvent(void) + { + return &(this->ums_event); + } + + UmsDeviceVector* UmsTask::GetUmsDevices(void) + { + return &(this->ums_devices); + } + /* USB host device connection task. */ - UsbHostTask::UsbHostTask(BooleanEvent *usb_host_event) : brls::RepeatingTask(TASK_INTERVAL) + UsbHostTask::UsbHostTask(void) : brls::RepeatingTask(NXDT_TASK_INTERVAL) { - this->usb_host_event = usb_host_event; + brls::RepeatingTask::start(); + brls::Logger::debug("USB host task started."); + } + + UsbHostTask::~UsbHostTask(void) + { + brls::Logger::debug("USB host task stopped."); } void UsbHostTask::run(retro_time_t current_time) @@ -96,9 +210,14 @@ namespace nxdt::tasks this->cur_usb_host_status = usbIsReady(); if (this->cur_usb_host_status != this->prev_usb_host_status) { - this->usb_host_event->fire(this->cur_usb_host_status); + this->usb_host_event.fire(this->cur_usb_host_status); this->prev_usb_host_status = this->cur_usb_host_status; brls::Logger::debug("USB host status change triggered: {}.", this->cur_usb_host_status); } } + + BooleanEvent* UsbHostTask::GetTaskEvent(void) + { + return &(this->usb_host_event); + } }