RootView: implement wrappers for public task functions.

Other changes include:

* GameCardTab: moved const strings to gamecard.c for easier maintenance.
* Codebase: reworked tab classes to make them use the wrappers provided by RootView instead of passing task object pointers.
This commit is contained in:
Pablo Curiel 2021-08-11 03:17:57 -04:00
parent 3dffce2995
commit 5a0543ef68
11 changed files with 112 additions and 94 deletions

View file

@ -268,6 +268,14 @@ bool gamecardGetHashFileSystemContext(u8 hfs_partition_type, HashFileSystemConte
/// If you need to get entry information by index, just retrieve the Hash FS context for the target partition and use Hash FS functions on it.
bool gamecardGetHashFileSystemEntryInfoByName(u8 hfs_partition_type, const char *entry_name, u64 *out_offset, u64 *out_size);
/// Takes a GameCardFwVersion value. Returns a pointer to a string that represents the minimum HOS version that matches the provided LAFW version.
/// Returns NULL if the provided value is out of range.
const char *gamecardGetRequiredHosVersionString(u64 fw_version);
/// Takes a GameCardCompatibilityType value. Returns a pointer to a string that represents the provided compatibility type.
/// Returns NULL if the provided value is out of range.
const char *gamecardGetCompatibilityTypeString(u8 compatibility_type);
#ifdef __cplusplus
}
#endif

View file

@ -24,7 +24,7 @@
#ifndef __GAMECARD_TAB_HPP__
#define __GAMECARD_TAB_HPP__
#include "tasks.hpp"
#include "root_view.hpp"
#include "layered_error_frame.hpp"
#include "focusable_item.hpp"
@ -35,7 +35,8 @@ namespace nxdt::views
typedef bool (*GameCardSizeFunc)(u64 *out_size);
private:
nxdt::tasks::GameCardTask *gc_status_task = nullptr;
RootView *root_view = nullptr;
nxdt::tasks::GameCardStatusEvent::Subscription gc_status_task_sub;
GameCardStatus gc_status = GameCardStatus_NotInserted;
@ -58,7 +59,7 @@ namespace nxdt::views
std::string GetFormattedSizeString(GameCardSizeFunc func);
public:
GameCardTab(nxdt::tasks::GameCardTask *gc_status_task);
GameCardTab(RootView *root_view);
~GameCardTab(void);
};
}

View file

@ -26,7 +26,7 @@
#include <borealis.hpp>
#include "tasks.hpp"
#include "root_view.hpp"
namespace nxdt::views
{
@ -96,7 +96,7 @@ namespace nxdt::views
class OptionsTab: public brls::List
{
private:
nxdt::tasks::StatusInfoTask *status_info_task = nullptr;
RootView *root_view = nullptr;
bool display_notification = true;
brls::menu_timer_t notification_timer = 0.0f;
@ -104,7 +104,7 @@ namespace nxdt::views
void DisplayNotification(std::string str);
public:
OptionsTab(nxdt::tasks::StatusInfoTask *status_info_task);
OptionsTab(RootView *root_view);
~OptionsTab(void);
};
}

View file

@ -26,6 +26,10 @@
#include "tasks.hpp"
#define EVENT_SUBSCRIPTION(func_name, event_type, task_name) \
ALWAYS_INLINE nxdt::tasks::event_type::Subscription Register##func_name##Listener(nxdt::tasks::event_type::Callback cb) { return this->task_name->RegisterListener(cb); } \
ALWAYS_INLINE void Unregister##func_name##Listener(nxdt::tasks::event_type::Subscription subscription) { this->task_name->UnregisterListener(subscription); }
namespace nxdt::views
{
class RootView: public brls::TabFrame
@ -58,7 +62,27 @@ namespace nxdt::views
~RootView(void);
static std::string GetFormattedDateString(const struct tm& timeinfo);
/* Wrappers for task functions. */
ALWAYS_INLINE bool IsInternetConnectionAvailable(void)
{
return this->status_info_task->IsInternetConnectionAvailable();
}
ALWAYS_INLINE const nxdt::tasks::TitleApplicationMetadataVector* GetApplicationMetadata(bool is_system)
{
return this->title_task->GetApplicationMetadata(is_system);
}
EVENT_SUBSCRIPTION(StatusInfoTask, StatusInfoEvent, status_info_task);
EVENT_SUBSCRIPTION(GameCardTask, GameCardStatusEvent, gc_status_task);
EVENT_SUBSCRIPTION(TitleTask, TitleEvent, title_task);
EVENT_SUBSCRIPTION(UmsTask, UmsEvent, ums_task);
EVENT_SUBSCRIPTION(UsbHostTask, UsbHostEvent, usb_host_task);
};
}
#undef EVENT_SUBSCRIPTION
#endif /* __ROOT_VIEW_HPP__ */

View file

@ -33,6 +33,10 @@
#include "core/usb.h"
#include "download_task.hpp"
#define EVENT_SUBSCRIPTION(event_type, event_name) \
ALWAYS_INLINE event_type::Subscription RegisterListener(event_type::Callback cb) { return this->event_name.subscribe(cb); } \
ALWAYS_INLINE void UnregisterListener(event_type::Subscription subscription) { this->event_name.unsubscribe(subscription); }
namespace nxdt::tasks
{
/* Used to hold status info data. */
@ -74,15 +78,7 @@ namespace nxdt::tasks
bool IsInternetConnectionAvailable(void);
ALWAYS_INLINE StatusInfoEvent::Subscription RegisterListener(StatusInfoEvent::Callback cb)
{
return this->status_info_event.subscribe(cb);
}
ALWAYS_INLINE void UnregisterListener(StatusInfoEvent::Subscription subscription)
{
this->status_info_event.unsubscribe(subscription);
}
EVENT_SUBSCRIPTION(StatusInfoEvent, status_info_event);
};
/* Gamecard task. */
@ -102,15 +98,7 @@ namespace nxdt::tasks
GameCardTask(void);
~GameCardTask(void);
ALWAYS_INLINE GameCardStatusEvent::Subscription RegisterListener(GameCardStatusEvent::Callback cb)
{
return this->gc_status_event.subscribe(cb);
}
ALWAYS_INLINE void UnregisterListener(GameCardStatusEvent::Subscription subscription)
{
this->gc_status_event.unsubscribe(subscription);
}
EVENT_SUBSCRIPTION(GameCardStatusEvent, gc_status_event);
};
/* Title task. */
@ -135,15 +123,7 @@ namespace nxdt::tasks
/* Intentionally left here to let system titles views retrieve metadata. */
const TitleApplicationMetadataVector* GetApplicationMetadata(bool is_system);
ALWAYS_INLINE TitleEvent::Subscription RegisterListener(TitleEvent::Callback cb)
{
return this->title_event.subscribe(cb);
}
ALWAYS_INLINE void UnregisterListener(TitleEvent::Subscription subscription)
{
this->title_event.unsubscribe(subscription);
}
EVENT_SUBSCRIPTION(TitleEvent, title_event);
};
/* USB Mass Storage task. */
@ -152,7 +132,6 @@ namespace nxdt::tasks
{
private:
UmsEvent ums_event;
UmsDeviceVector ums_devices;
void PopulateUmsDeviceVector(void);
@ -164,15 +143,7 @@ namespace nxdt::tasks
UmsTask(void);
~UmsTask(void);
ALWAYS_INLINE UmsEvent::Subscription RegisterListener(UmsEvent::Callback cb)
{
return this->ums_event.subscribe(cb);
}
ALWAYS_INLINE void UnregisterListener(UmsEvent::Subscription subscription)
{
this->ums_event.unsubscribe(subscription);
}
EVENT_SUBSCRIPTION(UmsEvent, ums_event);
};
/* USB host device connection task. */
@ -190,16 +161,10 @@ namespace nxdt::tasks
UsbHostTask(void);
~UsbHostTask(void);
ALWAYS_INLINE UsbHostEvent::Subscription RegisterListener(UsbHostEvent::Callback cb)
{
return this->usb_host_event.subscribe(cb);
}
ALWAYS_INLINE void UnregisterListener(UsbHostEvent::Subscription subscription)
{
this->usb_host_event.unsubscribe(subscription);
}
EVENT_SUBSCRIPTION(UsbHostEvent, usb_host_event);
};
}
#undef EVENT_SUBSCRIPTION
#endif /* __TASKS_HPP__ */

View file

@ -24,7 +24,7 @@
#ifndef __TITLES_TAB_HPP__
#define __TITLES_TAB_HPP__
#include "tasks.hpp"
#include "root_view.hpp"
#include "layered_error_frame.hpp"
namespace nxdt::views
@ -68,15 +68,15 @@ namespace nxdt::views
class TitlesTab: public LayeredErrorFrame
{
private:
nxdt::tasks::TitleTask *title_task = nullptr;
nxdt::tasks::TitleEvent::Subscription title_task_sub;
RootView *root_view = nullptr;
nxdt::tasks::TitleEvent::Subscription title_task_sub;
bool is_system = false;
void PopulateList(const nxdt::tasks::TitleApplicationMetadataVector* app_metadata);
public:
TitlesTab(nxdt::tasks::TitleTask *title_task, bool is_system);
TitlesTab(RootView *root_view, bool is_system);
~TitlesTab(void);
};
}

View file

@ -149,6 +149,20 @@ static const char *g_gameCardHfsPartitionNames[] = {
[GAMECARD_HFS_PARTITION_NAME_INDEX(GameCardHashFileSystemPartitionType_Boot)] = "boot"
};
static const char *g_gameCardHosVersionStrings[GameCardFwVersion_Count] = {
[GameCardFwVersion_ForDev] = "1.0.0",
[GameCardFwVersion_Since100NUP] = "1.0.0",
[GameCardFwVersion_Since400NUP] = "4.0.0",
[GameCardFwVersion_Since900NUP] = "9.0.0",
[GameCardFwVersion_Since1100NUP] = "11.0.0",
[GameCardFwVersion_Since1200NUP] = "12.0.0"
};
static const char *g_gameCardCompatibilityTypeStrings[GameCardCompatibilityType_Count] = {
[GameCardCompatibilityType_Normal] = "Normal",
[GameCardCompatibilityType_Terra] = "Terra"
};
/* Function prototypes. */
static bool gamecardGetLotusAsicFirmwareVersion(void);
@ -518,6 +532,16 @@ bool gamecardGetHashFileSystemEntryInfoByName(u8 hfs_partition_type, const char
return ret;
}
const char *gamecardGetRequiredHosVersionString(u64 fw_version)
{
return (fw_version < GameCardFwVersion_Count ? g_gameCardHosVersionStrings[fw_version] : NULL);
}
const char *gamecardGetCompatibilityTypeString(u8 compatibility_type)
{
return (compatibility_type < GameCardCompatibilityType_Count ? g_gameCardCompatibilityTypeStrings[compatibility_type] : NULL);
}
static bool gamecardGetLotusAsicFirmwareVersion(void)
{
u64 fw_version = 0;

View file

@ -27,21 +27,7 @@ using namespace i18n::literals; /* For _i18n. */
namespace nxdt::views
{
static const char *GameCardFwVersionStrings[GameCardFwVersion_Count] = {
[GameCardFwVersion_ForDev] = "1.0.0+",
[GameCardFwVersion_Since100NUP] = "1.0.0+",
[GameCardFwVersion_Since400NUP] = "4.0.0+",
[GameCardFwVersion_Since900NUP] = "9.0.0+",
[GameCardFwVersion_Since1100NUP] = "11.0.0+",
[GameCardFwVersion_Since1200NUP] = "12.0.0+"
};
static const char *GameCardCompatibilityTypeStrings[GameCardCompatibilityType_Count] = {
[GameCardCompatibilityType_Normal] = "Normal",
[GameCardCompatibilityType_Terra] = "Terra"
};
GameCardTab::GameCardTab(nxdt::tasks::GameCardTask *gc_status_task) : LayeredErrorFrame("gamecard_tab/error_frame/not_inserted"_i18n), gc_status_task(gc_status_task)
GameCardTab::GameCardTab(RootView *root_view) : LayeredErrorFrame("gamecard_tab/error_frame/not_inserted"_i18n), root_view(root_view)
{
/* Set custom spacing. */
this->list->setSpacing(this->list->getSpacing() / 2);
@ -64,6 +50,11 @@ namespace nxdt::views
this->list->addView(new brls::Header("gamecard_tab/list/dump_options"_i18n));
this->dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n);
/*this->dump_card_image->getClickEvent()->subscribe([](brls::View *view) {
});*/
this->list->addView(this->dump_card_image);
this->dump_certificate = new brls::ListItem("gamecard_tab/list/dump_certificate/label"_i18n, "gamecard_tab/list/dump_certificate/description"_i18n);
@ -82,7 +73,8 @@ namespace nxdt::views
this->list->addView(this->dump_hfs_partitions);
/* Subscribe to gamecard status event. */
this->gc_status_task_sub = this->gc_status_task->RegisterListener([this](GameCardStatus gc_status) {
this->gc_status_task_sub = this->root_view->RegisterGameCardTaskListener([this](GameCardStatus gc_status) {
/* Switch to the error layer if gamecard info hasn't been loaded. */
if (gc_status < GameCardStatus_InsertedAndInfoLoaded) this->SwitchLayerView(true);
switch(gc_status)
@ -104,6 +96,7 @@ namespace nxdt::views
break;
case GameCardStatus_InsertedAndInfoLoaded:
{
/* Fill properties table. */
GameCardInfo card_info = {0};
gamecardGetDecryptedCardInfoArea(&card_info);
@ -116,16 +109,17 @@ namespace nxdt::views
upp_version->minor_relstep, upp_version->value));
u64 fw_version = card_info.fw_version;
this->lafw_version->setValue(fmt::format("{} ({})", fw_version, fw_version >= GameCardFwVersion_Count ? "generic/unknown"_i18n : GameCardFwVersionStrings[fw_version]));
this->lafw_version->setValue(fmt::format("{} ({})", fw_version, fw_version >= GameCardFwVersion_Count ? "generic/unknown"_i18n : gamecardGetRequiredHosVersionString(fw_version)));
const VersionType2 *fw_mode = &(card_info.fw_mode);
this->sdk_version->setValue(fmt::format("{}.{}.{}-{} (v{})", fw_mode->major, fw_mode->minor, fw_mode->micro, fw_mode->relstep, fw_mode->value));
u8 compatibility_type = card_info.compatibility_type;
this->compatibility_type->setValue(fmt::format("{} ({})", \
compatibility_type >= GameCardCompatibilityType_Count ? "generic/unknown"_i18n : GameCardCompatibilityTypeStrings[compatibility_type], \
compatibility_type >= GameCardCompatibilityType_Count ? "generic/unknown"_i18n : gamecardGetCompatibilityTypeString(compatibility_type), \
compatibility_type));
/* Switch to the list view. */
this->SwitchLayerView(false);
break;
@ -134,6 +128,7 @@ namespace nxdt::views
break;
}
/* Update internal gamecard status. */
this->gc_status = gc_status;
});
}
@ -141,7 +136,7 @@ namespace nxdt::views
GameCardTab::~GameCardTab(void)
{
/* Unregister task listener. */
this->gc_status_task->UnregisterListener(this->gc_status_task_sub);
this->root_view->UnregisterGameCardTaskListener(this->gc_status_task_sub);
}
std::string GameCardTab::GetFormattedSizeString(GameCardSizeFunc func)

View file

@ -198,7 +198,7 @@ namespace nxdt::views
this->addStage(this->update_progress);
/* Register cancel action. */
this->registerAction("brls/hints/back"_i18n, brls::Key::B, [this](void){
this->registerAction("brls/hints/back"_i18n, brls::Key::B, [this](void) {
return this->onCancel();
});
@ -294,7 +294,7 @@ namespace nxdt::views
this->json_task.cancel();
/* Pop view. */
brls::Application::popView();
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
return true;
}
@ -341,7 +341,7 @@ namespace nxdt::views
}
/* Register update action. */
this->registerAction("options_tab/update_app/frame/update_action"_i18n, brls::Key::PLUS, [this](void){
this->registerAction("options_tab/update_app/frame/update_action"_i18n, brls::Key::PLUS, [this](void) {
/* Display update progress. */
this->DisplayUpdateProgress();
@ -358,12 +358,12 @@ namespace nxdt::views
void OptionsTabUpdateApplicationFrame::DisplayUpdateProgress(void)
{
/* Remove update action. */
this->registerAction("options_tab/update_app/frame/update_action"_i18n, brls::Key::PLUS, [](void){
this->registerAction("options_tab/update_app/frame/update_action"_i18n, brls::Key::PLUS, [](void) {
return true;
}, true);
/* Register cancel action once more, using a different label. */
this->registerAction("options_tab/update_dialog/cancel"_i18n, brls::Key::B, [this](void){
this->registerAction("options_tab/update_dialog/cancel"_i18n, brls::Key::B, [this](void) {
return this->onCancel();
});
@ -397,7 +397,7 @@ namespace nxdt::views
this->nextStage();
}
OptionsTab::OptionsTab(nxdt::tasks::StatusInfoTask *status_info_task) : brls::List(), status_info_task(status_info_task)
OptionsTab::OptionsTab(RootView *root_view) : brls::List(), root_view(root_view)
{
/* Set custom spacing. */
this->setSpacing(this->getSpacing() / 2);
@ -437,7 +437,7 @@ namespace nxdt::views
}, static_cast<unsigned>(configGetInteger("naming_convention")),
"options_tab/naming_convention/description"_i18n);
naming_convention->getValueSelectedEvent()->subscribe([](int selected){
naming_convention->getValueSelectedEvent()->subscribe([](int selected) {
/* Make sure the current value isn't out of bounds. */
if (selected < 0 || selected > static_cast<int>(TitleNamingConvention_Count)) return;
@ -453,7 +453,7 @@ namespace nxdt::views
brls::ListItem *update_nswdb_xml = new brls::ListItem("options_tab/update_nswdb_xml/label"_i18n, "options_tab/update_nswdb_xml/description"_i18n);
update_nswdb_xml->getClickEvent()->subscribe([this](brls::View* view) {
if (!this->status_info_task->IsInternetConnectionAvailable())
if (!this->root_view->IsInternetConnectionAvailable())
{
/* Display a notification if no Internet connection is available. */
this->DisplayNotification("options_tab/notifications/no_internet_connection"_i18n);
@ -477,7 +477,7 @@ namespace nxdt::views
this->DisplayNotification("options_tab/notifications/is_nso"_i18n);
return;
} else
if (!this->status_info_task->IsInternetConnectionAvailable())
if (!this->root_view->IsInternetConnectionAvailable())
{
/* Display a notification if no Internet connection is available. */
this->DisplayNotification("options_tab/notifications/no_internet_connection"_i18n);
@ -491,7 +491,7 @@ namespace nxdt::views
}
/* Display update frame. */
brls::Application::pushView(new OptionsTabUpdateApplicationFrame(), brls::ViewAnimation::FADE, false);
brls::Application::pushView(new OptionsTabUpdateApplicationFrame(), brls::ViewAnimation::SLIDE_LEFT, false);
});
this->addView(update_app);

View file

@ -94,23 +94,23 @@ namespace nxdt::views
this->usb_host_task = new nxdt::tasks::UsbHostTask();
/* Add tabs. */
GameCardTab *gamecard_tab = new GameCardTab(this->gc_status_task);
GameCardTab *gamecard_tab = new GameCardTab(this);
this->addTab("root_view/tabs/gamecard"_i18n, gamecard_tab);
gamecard_tab->SetParentSidebarItem(static_cast<brls::SidebarItem*>(this->sidebar->getChild(this->sidebar->getViewsCount() - 1)));
this->addSeparator();
TitlesTab *user_titles_tab = new TitlesTab(this->title_task, false);
TitlesTab *user_titles_tab = new TitlesTab(this, false);
this->addTab("root_view/tabs/user_titles"_i18n, user_titles_tab);
user_titles_tab->SetParentSidebarItem(static_cast<brls::SidebarItem*>(this->sidebar->getChild(this->sidebar->getViewsCount() - 1)));
TitlesTab *system_titles_tab = new TitlesTab(this->title_task, true);
TitlesTab *system_titles_tab = new TitlesTab(this, true);
this->addTab("root_view/tabs/system_titles"_i18n, system_titles_tab);
system_titles_tab->SetParentSidebarItem(static_cast<brls::SidebarItem*>(this->sidebar->getChild(this->sidebar->getViewsCount() - 1)));
this->addSeparator();
this->addTab("root_view/tabs/options"_i18n, new OptionsTab(this->status_info_task));
this->addTab("root_view/tabs/options"_i18n, new OptionsTab(this));
this->addSeparator();
@ -154,6 +154,7 @@ namespace nxdt::views
this->status_info_task->UnregisterListener(this->status_info_task_sub);
/* Stop background tasks. */
this->status_info_task->stop();
this->gc_status_task->stop();
this->title_task->stop();
this->ums_task->stop();

View file

@ -75,15 +75,15 @@ namespace nxdt::views
this->setValue(fmt::format("{:016X}", this->app_metadata->title_id), false, false);
}
TitlesTab::TitlesTab(nxdt::tasks::TitleTask *title_task, bool is_system) : LayeredErrorFrame("titles_tab/no_titles_available"_i18n), title_task(title_task), is_system(is_system)
TitlesTab::TitlesTab(RootView *root_view, bool is_system) : LayeredErrorFrame("titles_tab/no_titles_available"_i18n), root_view(root_view), is_system(is_system)
{
/* Populate list. */
this->PopulateList(this->title_task->GetApplicationMetadata(this->is_system));
this->PopulateList(this->root_view->GetApplicationMetadata(this->is_system));
/* Subscribe to the title event if this is the user titles tab. */
if (!this->is_system)
{
this->title_task_sub = this->title_task->RegisterListener([this](const nxdt::tasks::TitleApplicationMetadataVector* app_metadata) {
this->title_task_sub = this->root_view->RegisterTitleTaskListener([this](const nxdt::tasks::TitleApplicationMetadataVector* app_metadata) {
/* Update list. */
this->PopulateList(app_metadata);
});
@ -93,7 +93,7 @@ namespace nxdt::views
TitlesTab::~TitlesTab(void)
{
/* Unregister task listener if this is the user titles tab. */
if (!this->is_system) this->title_task->UnregisterListener(this->title_task_sub);
if (!this->is_system) this->root_view->UnregisterTitleTaskListener(this->title_task_sub);
}
void TitlesTab::PopulateList(const nxdt::tasks::TitleApplicationMetadataVector* app_metadata)
@ -120,7 +120,7 @@ namespace nxdt::views
TitlesTabItem *title = new TitlesTabItem(cur_app_metadata, this->is_system);
/* Register click event. */
title->getClickEvent()->subscribe([](brls::View *view){
title->getClickEvent()->subscribe([](brls::View *view) {
TitlesTabItem *item = static_cast<TitlesTabItem*>(view);
const TitleApplicationMetadata *app_metadata = item->GetApplicationMetadata();
bool is_system = item->IsSystemTitle();