mirror of
https://github.com/XorTroll/uLaunch
synced 2024-11-28 23:00:19 +00:00
Cleanup and improvements
This commit is contained in:
parent
7853802391
commit
ae77e3225e
9 changed files with 136 additions and 127 deletions
|
@ -3,6 +3,7 @@
|
|||
#include <ul_Include.hpp>
|
||||
#include <hb/hb_Target.hpp>
|
||||
#include <fs/fs_Stdio.hpp>
|
||||
#include <util/util_Convert.hpp>
|
||||
|
||||
namespace cfg {
|
||||
|
||||
|
@ -130,7 +131,10 @@ namespace cfg {
|
|||
void RenameFolder(TitleList &list, const std::string &old_name, const std::string &new_name);
|
||||
bool ExistsRecord(TitleList &list, TitleRecord record);
|
||||
|
||||
std::string GetTitleCacheIconPath(u64 app_id);
|
||||
inline std::string GetTitleCacheIconPath(u64 app_id) {
|
||||
return UL_BASE_SD_DIR "/title/" + util::FormatApplicationId(app_id) + ".jpg";
|
||||
}
|
||||
|
||||
std::string GetNROCacheIconPath(const std::string &path);
|
||||
|
||||
}
|
|
@ -25,7 +25,7 @@ namespace os {
|
|||
};
|
||||
|
||||
std::string GetLanguageName(u32 idx);
|
||||
std::vector<std::string> &GetLanguageNameList();
|
||||
const std::vector<std::string> &GetLanguageNameList();
|
||||
|
||||
u32 GetBatteryLevel();
|
||||
bool IsConsoleCharging();
|
||||
|
|
|
@ -1,33 +1,38 @@
|
|||
#include <am/am_Application.hpp>
|
||||
|
||||
namespace am
|
||||
{
|
||||
extern bool g_home_has_focus;
|
||||
static AppletApplication g_application_holder;
|
||||
static u64 g_last_app_id;
|
||||
namespace am {
|
||||
|
||||
namespace {
|
||||
|
||||
AppletApplication g_ApplicationHolder;
|
||||
u64 g_LastApplicationId;
|
||||
|
||||
}
|
||||
|
||||
extern bool g_DaemonHasFocus;
|
||||
|
||||
bool ApplicationIsActive() {
|
||||
if(g_application_holder.StateChangedEvent.revent == INVALID_HANDLE) {
|
||||
if(g_ApplicationHolder.StateChangedEvent.revent == INVALID_HANDLE) {
|
||||
return false;
|
||||
}
|
||||
if(!serviceIsActive(&g_application_holder.s)) {
|
||||
if(!serviceIsActive(&g_ApplicationHolder.s)) {
|
||||
return false;
|
||||
}
|
||||
return !appletApplicationCheckFinished(&g_application_holder);
|
||||
return !appletApplicationCheckFinished(&g_ApplicationHolder);
|
||||
}
|
||||
|
||||
void ApplicationTerminate() {
|
||||
appletApplicationRequestExit(&g_application_holder);
|
||||
g_home_has_focus = true;
|
||||
appletApplicationRequestExit(&g_ApplicationHolder);
|
||||
g_DaemonHasFocus = true;
|
||||
}
|
||||
|
||||
Result ApplicationStart(u64 app_id, bool system, AccountUid user_id, void *data, size_t size) {
|
||||
appletApplicationClose(&g_application_holder);
|
||||
appletApplicationClose(&g_ApplicationHolder);
|
||||
if(system) {
|
||||
R_TRY(appletCreateSystemApplication(&g_application_holder, app_id));
|
||||
R_TRY(appletCreateSystemApplication(&g_ApplicationHolder, app_id));
|
||||
}
|
||||
else {
|
||||
R_TRY(appletCreateApplication(&g_application_holder, app_id));
|
||||
R_TRY(appletCreateApplication(&g_ApplicationHolder, app_id));
|
||||
}
|
||||
|
||||
if(accountUidIsValid(&user_id)) {
|
||||
|
@ -40,20 +45,20 @@ namespace am
|
|||
}
|
||||
|
||||
R_TRY(appletUnlockForeground());
|
||||
R_TRY(appletApplicationStart(&g_application_holder));
|
||||
R_TRY(appletApplicationStart(&g_ApplicationHolder));
|
||||
R_TRY(ApplicationSetForeground());
|
||||
|
||||
g_last_app_id = app_id;
|
||||
g_LastApplicationId = app_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ApplicationHasForeground() {
|
||||
return !g_home_has_focus;
|
||||
return !g_DaemonHasFocus;
|
||||
}
|
||||
|
||||
Result ApplicationSetForeground() {
|
||||
R_TRY(appletApplicationRequestForApplicationToGetForeground(&g_application_holder));
|
||||
g_home_has_focus = false;
|
||||
R_TRY(appletApplicationRequestForApplicationToGetForeground(&g_ApplicationHolder));
|
||||
g_DaemonHasFocus = false;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
|
@ -64,12 +69,12 @@ namespace am
|
|||
appletStorageClose(&st);
|
||||
});
|
||||
R_TRY(appletStorageWrite(&st, 0, data, size));
|
||||
R_TRY(appletApplicationPushLaunchParameter(&g_application_holder, kind, &st));
|
||||
R_TRY(appletApplicationPushLaunchParameter(&g_ApplicationHolder, kind, &st));
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
u64 ApplicationGetId() {
|
||||
return g_last_app_id;
|
||||
return g_LastApplicationId;
|
||||
}
|
||||
|
||||
bool ApplicationNeedsUser(u64 app_id) {
|
||||
|
|
|
@ -3,16 +3,15 @@
|
|||
|
||||
namespace am {
|
||||
|
||||
bool g_home_has_focus = true;
|
||||
extern AppletHolder g_applet_holder;
|
||||
bool g_DaemonHasFocus = true;
|
||||
|
||||
bool HomeMenuHasForeground() {
|
||||
return g_home_has_focus;
|
||||
return g_DaemonHasFocus;
|
||||
}
|
||||
|
||||
Result HomeMenuSetForeground() {
|
||||
R_TRY(appletRequestToGetForeground());
|
||||
g_home_has_focus = true;
|
||||
g_DaemonHasFocus = true;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,95 +1,98 @@
|
|||
#include <am/am_LibraryApplet.hpp>
|
||||
#include <map>
|
||||
|
||||
namespace am
|
||||
{
|
||||
static AppletHolder g_applet_holder;
|
||||
static AppletId g_menu_applet_id = InvalidAppletId;
|
||||
static AppletId g_last_applet_id = InvalidAppletId;
|
||||
namespace am {
|
||||
|
||||
static std::map<u64, AppletId> g_applet_id_table = {
|
||||
{ 0x0100000000001001, AppletId_auth },
|
||||
{ 0x0100000000001002, AppletId_cabinet },
|
||||
{ 0x0100000000001003, AppletId_controller },
|
||||
{ 0x0100000000001004, AppletId_dataErase },
|
||||
{ 0x0100000000001005, AppletId_error },
|
||||
{ 0x0100000000001006, AppletId_netConnect },
|
||||
{ 0x0100000000001007, AppletId_playerSelect },
|
||||
{ 0x0100000000001008, AppletId_swkbd },
|
||||
{ 0x0100000000001009, AppletId_miiEdit },
|
||||
{ 0x010000000000100A, AppletId_web },
|
||||
{ 0x010000000000100B, AppletId_shop },
|
||||
{ 0x010000000000100D, AppletId_photoViewer },
|
||||
{ 0x010000000000100E, AppletId_set },
|
||||
{ 0x010000000000100F, AppletId_offlineWeb },
|
||||
{ 0x0100000000001010, AppletId_loginShare },
|
||||
{ 0x0100000000001011, AppletId_wifiWebAuth },
|
||||
{ 0x0100000000001013, AppletId_myPage }
|
||||
};
|
||||
namespace {
|
||||
|
||||
AppletHolder g_AppletHolder;
|
||||
AppletId g_MenuAppletId = InvalidAppletId;
|
||||
AppletId g_LastAppletId = InvalidAppletId;
|
||||
|
||||
const std::map<u64, AppletId> g_AppletIdTable = {
|
||||
{ 0x0100000000001001, AppletId_auth },
|
||||
{ 0x0100000000001002, AppletId_cabinet },
|
||||
{ 0x0100000000001003, AppletId_controller },
|
||||
{ 0x0100000000001004, AppletId_dataErase },
|
||||
{ 0x0100000000001005, AppletId_error },
|
||||
{ 0x0100000000001006, AppletId_netConnect },
|
||||
{ 0x0100000000001007, AppletId_playerSelect },
|
||||
{ 0x0100000000001008, AppletId_swkbd },
|
||||
{ 0x0100000000001009, AppletId_miiEdit },
|
||||
{ 0x010000000000100A, AppletId_web },
|
||||
{ 0x010000000000100B, AppletId_shop },
|
||||
{ 0x010000000000100D, AppletId_photoViewer },
|
||||
{ 0x010000000000100E, AppletId_set },
|
||||
{ 0x010000000000100F, AppletId_offlineWeb },
|
||||
{ 0x0100000000001010, AppletId_loginShare },
|
||||
{ 0x0100000000001011, AppletId_wifiWebAuth },
|
||||
{ 0x0100000000001013, AppletId_myPage }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool LibraryAppletIsActive() {
|
||||
if(g_applet_holder.StateChangedEvent.revent == INVALID_HANDLE) {
|
||||
if(g_AppletHolder.StateChangedEvent.revent == INVALID_HANDLE) {
|
||||
return false;
|
||||
}
|
||||
if(!serviceIsActive(&g_applet_holder.s)) {
|
||||
if(!serviceIsActive(&g_AppletHolder.s)) {
|
||||
return false;
|
||||
}
|
||||
return !appletHolderCheckFinished(&g_applet_holder);
|
||||
return !appletHolderCheckFinished(&g_AppletHolder);
|
||||
}
|
||||
|
||||
void LibraryAppletSetMenuAppletId(AppletId id) {
|
||||
g_menu_applet_id = id;
|
||||
g_MenuAppletId = id;
|
||||
}
|
||||
|
||||
AppletId LibraryAppletGetMenuAppletId() {
|
||||
return g_menu_applet_id;
|
||||
return g_MenuAppletId;
|
||||
}
|
||||
|
||||
bool LibraryAppletIsMenu() {
|
||||
return LibraryAppletIsActive() && (g_menu_applet_id != InvalidAppletId) && (LibraryAppletGetId() == g_menu_applet_id);
|
||||
return LibraryAppletIsActive() && (g_MenuAppletId != InvalidAppletId) && (LibraryAppletGetId() == g_MenuAppletId);
|
||||
}
|
||||
|
||||
void LibraryAppletTerminate() {
|
||||
// Give it 15 seconds
|
||||
appletHolderRequestExitOrTerminate(&g_applet_holder, 15'000'000'000ul);
|
||||
appletHolderRequestExitOrTerminate(&g_AppletHolder, 15'000'000'000ul);
|
||||
}
|
||||
|
||||
Result LibraryAppletStart(AppletId id, u32 la_version, void *in_data, size_t in_size) {
|
||||
if(LibraryAppletIsActive()) {
|
||||
LibraryAppletTerminate();
|
||||
}
|
||||
appletHolderClose(&g_applet_holder);
|
||||
appletHolderClose(&g_AppletHolder);
|
||||
LibAppletArgs largs;
|
||||
libappletArgsCreate(&largs, la_version);
|
||||
R_TRY(appletCreateLibraryApplet(&g_applet_holder, id, LibAppletMode_AllForeground));
|
||||
R_TRY(libappletArgsPush(&largs, &g_applet_holder));
|
||||
R_TRY(appletCreateLibraryApplet(&g_AppletHolder, id, LibAppletMode_AllForeground));
|
||||
R_TRY(libappletArgsPush(&largs, &g_AppletHolder));
|
||||
if(in_size > 0) {
|
||||
R_TRY(LibraryAppletSend(in_data, in_size));
|
||||
}
|
||||
R_TRY(appletHolderStart(&g_applet_holder));
|
||||
g_last_applet_id = id;
|
||||
R_TRY(appletHolderStart(&g_AppletHolder));
|
||||
g_LastAppletId = id;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result LibraryAppletSend(void *data, size_t size) {
|
||||
return libappletPushInData(&g_applet_holder, data, size);
|
||||
return libappletPushInData(&g_AppletHolder, data, size);
|
||||
}
|
||||
|
||||
Result LibraryAppletRead(void *data, size_t size) {
|
||||
return libappletPopOutData(&g_applet_holder, data, size, nullptr);
|
||||
return libappletPopOutData(&g_AppletHolder, data, size, nullptr);
|
||||
}
|
||||
|
||||
Result LibraryAppletDaemonLaunchWith(AppletId id, u32 la_version, std::function<void(AppletHolder*)> on_prepare, std::function<void(AppletHolder*)> on_finish, std::function<bool()> on_wait) {
|
||||
if(LibraryAppletIsActive()) {
|
||||
LibraryAppletTerminate();
|
||||
}
|
||||
appletHolderClose(&g_applet_holder);
|
||||
appletHolderClose(&g_AppletHolder);
|
||||
LibAppletArgs largs;
|
||||
libappletArgsCreate(&largs, la_version);
|
||||
R_TRY(appletCreateLibraryApplet(&g_applet_holder, id, LibAppletMode_AllForeground));
|
||||
R_TRY(libappletArgsPush(&largs, &g_applet_holder));
|
||||
on_prepare(&g_applet_holder);
|
||||
R_TRY(appletHolderStart(&g_applet_holder));
|
||||
R_TRY(appletCreateLibraryApplet(&g_AppletHolder, id, LibAppletMode_AllForeground));
|
||||
R_TRY(libappletArgsPush(&largs, &g_AppletHolder));
|
||||
on_prepare(&g_AppletHolder);
|
||||
R_TRY(appletHolderStart(&g_AppletHolder));
|
||||
while(true) {
|
||||
if(!LibraryAppletIsActive()) {
|
||||
break;
|
||||
|
@ -98,15 +101,15 @@ namespace am
|
|||
LibraryAppletTerminate();
|
||||
break;
|
||||
}
|
||||
svcSleepThread(10'000'000l);
|
||||
svcSleepThread(10'000'000ul);
|
||||
}
|
||||
on_finish(&g_applet_holder);
|
||||
appletHolderClose(&g_applet_holder);
|
||||
on_finish(&g_AppletHolder);
|
||||
appletHolderClose(&g_AppletHolder);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
u64 LibraryAppletGetProgramIdForAppletId(AppletId id) {
|
||||
for(auto &[program_id, applet_id] : g_applet_id_table) {
|
||||
for(auto &[program_id, applet_id] : g_AppletIdTable) {
|
||||
if(applet_id == id) {
|
||||
return program_id;
|
||||
}
|
||||
|
@ -115,17 +118,17 @@ namespace am
|
|||
}
|
||||
|
||||
AppletId LibraryAppletGetAppletIdForProgramId(u64 id) {
|
||||
auto it = g_applet_id_table.find(id);
|
||||
if(it != g_applet_id_table.end()) {
|
||||
auto it = g_AppletIdTable.find(id);
|
||||
if(it != g_AppletIdTable.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return InvalidAppletId;
|
||||
}
|
||||
|
||||
AppletId LibraryAppletGetId() {
|
||||
auto idcopy = g_last_applet_id;
|
||||
auto idcopy = g_LastAppletId;
|
||||
if(!LibraryAppletIsActive()) {
|
||||
g_last_applet_id = InvalidAppletId;
|
||||
g_LastAppletId = InvalidAppletId;
|
||||
}
|
||||
return idcopy;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
#include <os/os_Titles.hpp>
|
||||
#include <util/util_Misc.hpp>
|
||||
#include <util/util_String.hpp>
|
||||
#include <fs/fs_Stdio.hpp>
|
||||
#include <db/db_Save.hpp>
|
||||
#include <util/util_Convert.hpp>
|
||||
|
||||
namespace cfg {
|
||||
|
||||
|
@ -218,8 +216,7 @@ namespace cfg {
|
|||
return cfg;
|
||||
}
|
||||
|
||||
Config LoadConfig()
|
||||
{
|
||||
Config LoadConfig() {
|
||||
// Default constructor sets everything
|
||||
Config cfg = {};
|
||||
JSON cfgjson;
|
||||
|
@ -248,9 +245,9 @@ namespace cfg {
|
|||
return CreateNewAndLoadConfig();
|
||||
}
|
||||
|
||||
void SaveConfig(const Config &cfg)
|
||||
{
|
||||
void SaveConfig(const Config &cfg) {
|
||||
fs::DeleteFile(CFG_CONFIG_JSON);
|
||||
|
||||
auto json = JSON::object();
|
||||
json["theme_name"] = cfg.theme_name;
|
||||
json["viewer_usb_enabled"] = cfg.viewer_usb_enabled;
|
||||
|
@ -258,13 +255,13 @@ namespace cfg {
|
|||
json["menu_program_id"] = util::FormatApplicationId(cfg.menu_program_id);
|
||||
json["homebrew_applet_program_id"] = util::FormatApplicationId(cfg.homebrew_applet_program_id);
|
||||
json["homebrew_title_application_id"] = util::FormatApplicationId(cfg.homebrew_title_application_id);
|
||||
|
||||
std::ofstream ofs(CFG_CONFIG_JSON);
|
||||
ofs << std::setw(4) << json;
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
void SaveRecord(TitleRecord &record)
|
||||
{
|
||||
void SaveRecord(TitleRecord &record) {
|
||||
auto entry = JSON::object();
|
||||
entry["type"] = record.title_type;
|
||||
entry["folder"] = record.sub_folder;
|
||||
|
@ -507,8 +504,7 @@ namespace cfg {
|
|||
return title_found;
|
||||
}
|
||||
|
||||
TitleFolder &FindFolderByName(TitleList &list, const std::string &name)
|
||||
{
|
||||
TitleFolder &FindFolderByName(TitleList &list, const std::string &name) {
|
||||
if(!name.empty()) {
|
||||
auto f = STL_FIND_IF(list.folders, fld, (fld.name == name));
|
||||
if(STL_FOUND(list.folders, f)) {
|
||||
|
@ -529,9 +525,8 @@ namespace cfg {
|
|||
}
|
||||
}
|
||||
|
||||
bool ExistsRecord(TitleList &list, TitleRecord record)
|
||||
{
|
||||
bool title_found = false;
|
||||
bool ExistsRecord(TitleList &list, TitleRecord record) {
|
||||
auto title_found = false;
|
||||
TitleRecord record_copy = {};
|
||||
std::string recjson;
|
||||
const auto type = static_cast<TitleType>(record.title_type);
|
||||
|
@ -670,11 +665,6 @@ namespace cfg {
|
|||
return list;
|
||||
}
|
||||
|
||||
std::string GetTitleCacheIconPath(u64 app_id) {
|
||||
auto strappid = util::FormatApplicationId(app_id);
|
||||
return UL_BASE_SD_DIR "/title/" + strappid + ".jpg";
|
||||
}
|
||||
|
||||
std::string GetNROCacheIconPath(const std::string &path) {
|
||||
char pathcopy[FS_MAX_PATH] = {0};
|
||||
strcpy(pathcopy, path.c_str());
|
||||
|
@ -683,10 +673,12 @@ namespace cfg {
|
|||
std::string out = UL_BASE_SD_DIR "/nro/";
|
||||
std::stringstream strm;
|
||||
strm << out;
|
||||
for(u32 i = 0; i < 0x10; i++) {
|
||||
// Use the first half of the hash, like N does with NCAs.
|
||||
for(u32 i = 0; i < sizeof(hash) / 2; i++) {
|
||||
strm << std::setw(2) << std::setfill('0') << std::hex << std::nouppercase << (u32)hash[i];
|
||||
}
|
||||
strm << ".jpg";
|
||||
return strm.str();
|
||||
}
|
||||
|
||||
}
|
|
@ -48,7 +48,7 @@ namespace net {
|
|||
std::string GetConsoleIPAddress() {
|
||||
char ipaddr[0x20] = {0};
|
||||
auto ip = gethostid();
|
||||
sprintf(ipaddr, "%lu.%lu.%lu.%lu", (ip & 0xff000000) >> 24, (ip & 0x00ff0000) >> 16, (ip & 0x0000ff00) >> 8, (ip & 0x000000ff));
|
||||
sprintf(ipaddr, "%lu.%lu.%lu.%lu", (ip & 0x000000FF), (ip & 0x0000FF00) >> 8, (ip & 0x00FF0000) >> 16, (ip & 0xFF000000) >> 24);
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@ namespace os {
|
|||
s32 acc_count = 0;
|
||||
R_TRY(accountListAllUsers(uids, ACC_USER_LIST_SIZE, &acc_count));
|
||||
for(s32 i = 0; i < acc_count; i++) {
|
||||
out_accounts.push_back(uids[i]);
|
||||
auto uid = uids[i];
|
||||
out_accounts.push_back(uid);
|
||||
if(dump_icon) {
|
||||
AccountProfile prof;
|
||||
auto rc = accountGetProfile(&prof, uids[i]);
|
||||
auto rc = accountGetProfile(&prof, uid);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
u32 imgsz = 0;
|
||||
rc = accountProfileGetImageSize(&prof, &imgsz);
|
||||
|
@ -27,7 +28,7 @@ namespace os {
|
|||
u32 tmpsz;
|
||||
rc = accountProfileLoadImage(&prof, imgbuf, imgsz, &tmpsz);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
auto iconcache = GetIconCacheImagePath(uids[i]);
|
||||
auto iconcache = GetIconCacheImagePath(uid);
|
||||
fs::WriteFile(iconcache, imgbuf, imgsz, true);
|
||||
}
|
||||
delete[] imgbuf;
|
||||
|
|
|
@ -3,35 +3,39 @@
|
|||
|
||||
namespace os {
|
||||
|
||||
static std::vector<std::string> g_lang_names = {
|
||||
"Japanese",
|
||||
"American English",
|
||||
"Français",
|
||||
"Deutsch",
|
||||
"Italiano",
|
||||
"Español",
|
||||
"Chinese",
|
||||
"Korean",
|
||||
"Nederlands",
|
||||
"Português",
|
||||
"Русский",
|
||||
"Taiwanese",
|
||||
"British English",
|
||||
"Français canadien",
|
||||
"Español latino",
|
||||
"Chinese (simplified)",
|
||||
"Chinese (traditional)"
|
||||
};
|
||||
namespace {
|
||||
|
||||
const std::vector<std::string> g_LanguageNameList = {
|
||||
"Japanese",
|
||||
"American English",
|
||||
"Français",
|
||||
"Deutsch",
|
||||
"Italiano",
|
||||
"Español",
|
||||
"Chinese",
|
||||
"Korean",
|
||||
"Nederlands",
|
||||
"Português",
|
||||
"Русский",
|
||||
"Taiwanese",
|
||||
"British English",
|
||||
"Français canadien",
|
||||
"Español latino",
|
||||
"Chinese (simplified)",
|
||||
"Chinese (traditional)"
|
||||
};
|
||||
|
||||
std::string GetLanguageName(u32 idx) {
|
||||
if(idx >= g_lang_names.size()) {
|
||||
return "";
|
||||
}
|
||||
return g_lang_names[idx];
|
||||
}
|
||||
|
||||
std::vector<std::string> &GetLanguageNameList() {
|
||||
return g_lang_names;
|
||||
std::string GetLanguageName(u32 idx) {
|
||||
if(idx >= g_LanguageNameList.size()) {
|
||||
return "";
|
||||
}
|
||||
return g_LanguageNameList[idx];
|
||||
}
|
||||
|
||||
const std::vector<std::string> &GetLanguageNameList() {
|
||||
return g_LanguageNameList;
|
||||
}
|
||||
|
||||
u32 GetBatteryLevel() {
|
||||
|
@ -53,6 +57,7 @@ namespace os {
|
|||
}
|
||||
|
||||
// Thanks Goldleaf
|
||||
|
||||
std::string GetCurrentTime() {
|
||||
auto time_val = time(nullptr);
|
||||
auto local_time = localtime(&time_val);
|
||||
|
|
Loading…
Reference in a new issue