2023-03-22 11:34:48 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <mutex>
|
|
|
|
#include <map>
|
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
#include "Common/System/System.h"
|
|
|
|
|
2023-03-24 20:05:48 +01:00
|
|
|
class Path;
|
|
|
|
|
2023-03-22 11:34:48 +01:00
|
|
|
typedef std::function<void(const char *responseString, int responseValue)> RequestCallback;
|
2023-03-25 18:48:50 +01:00
|
|
|
typedef std::function<void()> RequestFailedCallback;
|
2023-03-22 11:34:48 +01:00
|
|
|
|
2023-03-28 14:25:30 +02:00
|
|
|
// Platforms often have to process requests asynchronously, on wildly different threads,
|
|
|
|
// and then somehow pass a response back to the main thread (especially Android...)
|
2023-03-22 11:34:48 +01:00
|
|
|
// This acts as bridge and buffer.
|
2023-03-28 14:25:30 +02:00
|
|
|
// However - the actual request is performed on the current thread, it's the callbacks that are "made threadsafe"
|
|
|
|
// by running them on the main thread. So beware in your implementations!
|
2023-03-22 11:34:48 +01:00
|
|
|
class RequestManager {
|
|
|
|
public:
|
|
|
|
// These requests are to be handled by platform implementations.
|
|
|
|
// The callback you pass in will be called on the main thread later.
|
2023-03-25 18:48:50 +01:00
|
|
|
// Params are at the end since it's the part most likely to recieve additions in the future,
|
|
|
|
// now that we have both callbacks.
|
|
|
|
bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, RequestFailedCallback failedCallback, const std::string ¶m1, const std::string ¶m2, int param3);
|
2023-03-22 11:34:48 +01:00
|
|
|
|
|
|
|
// Called by the platform implementation, when it's finished with a request.
|
2023-03-22 12:26:14 +01:00
|
|
|
void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0);
|
|
|
|
void PostSystemFailure(int requestId);
|
2023-03-22 11:34:48 +01:00
|
|
|
|
2023-08-07 22:44:06 +02:00
|
|
|
// This must be called every frame from the beginning of NativeFrame().
|
2023-03-22 11:34:48 +01:00
|
|
|
// This will call the callback of any finished requests.
|
|
|
|
void ProcessRequests();
|
|
|
|
|
2023-03-22 12:26:14 +01:00
|
|
|
// Unclear if we need this...
|
|
|
|
void Clear();
|
|
|
|
|
2023-03-22 11:34:48 +01:00
|
|
|
private:
|
|
|
|
struct PendingRequest {
|
|
|
|
SystemRequestType type;
|
|
|
|
RequestCallback callback;
|
2023-03-25 18:48:50 +01:00
|
|
|
RequestFailedCallback failedCallback;
|
2023-03-22 11:34:48 +01:00
|
|
|
};
|
|
|
|
|
2023-03-25 18:48:50 +01:00
|
|
|
struct CallbackPair {
|
|
|
|
RequestCallback callback;
|
|
|
|
RequestFailedCallback failedCallback;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::map<int, CallbackPair> callbackMap_;
|
2023-03-22 11:34:48 +01:00
|
|
|
std::mutex callbackMutex_;
|
|
|
|
|
2023-03-25 18:48:50 +01:00
|
|
|
struct PendingSuccess {
|
2023-03-22 11:34:48 +01:00
|
|
|
std::string responseString;
|
|
|
|
int responseValue;
|
|
|
|
RequestCallback callback;
|
|
|
|
};
|
|
|
|
|
2023-03-25 18:48:50 +01:00
|
|
|
struct PendingFailure {
|
|
|
|
RequestFailedCallback callback;
|
|
|
|
};
|
|
|
|
|
2023-07-15 12:21:37 +02:00
|
|
|
// Let's start at 10 to get a recognizably valid ID in logs.
|
|
|
|
int idCounter_ = 10;
|
2023-03-25 18:48:50 +01:00
|
|
|
std::vector<PendingSuccess> pendingSuccesses_;
|
|
|
|
std::vector<PendingFailure> pendingFailures_;
|
2023-03-22 11:34:48 +01:00
|
|
|
std::mutex responseMutex_;
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *RequestTypeAsString(SystemRequestType type);
|
|
|
|
|
2023-03-22 12:26:14 +01:00
|
|
|
extern RequestManager g_requestManager;
|
|
|
|
|
|
|
|
// Wrappers for easy requests.
|
2023-06-19 23:22:44 +02:00
|
|
|
// NOTE: Semantics have changed - this no longer calls the callback on cancellation, instead you
|
|
|
|
// can specify a different callback for that.
|
2023-03-25 18:48:50 +01:00
|
|
|
inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, failedCallback, title, defaultValue, 0);
|
2023-03-22 12:26:14 +01:00
|
|
|
}
|
2023-03-22 13:43:44 +01:00
|
|
|
|
2023-06-19 23:22:44 +02:00
|
|
|
// This one will pop up a special image browser if available. You can also pick
|
2023-03-22 15:52:11 +01:00
|
|
|
// images with the file browser below.
|
2023-03-25 18:48:50 +01:00
|
|
|
inline void System_BrowseForImage(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, failedCallback, title, "", 0);
|
2023-03-22 15:21:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
enum class BrowseFileType {
|
|
|
|
BOOTABLE,
|
2023-03-22 15:52:11 +01:00
|
|
|
IMAGE,
|
2023-03-22 15:21:03 +01:00
|
|
|
INI,
|
2023-03-23 01:16:12 +01:00
|
|
|
DB,
|
2023-07-16 12:14:40 +02:00
|
|
|
SOUND_EFFECT,
|
2023-03-22 15:21:03 +01:00
|
|
|
ANY,
|
|
|
|
};
|
|
|
|
|
2023-03-25 18:48:50 +01:00
|
|
|
inline void System_BrowseForFile(const std::string &title, BrowseFileType type, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, callback, failedCallback, title, "", (int)type);
|
2023-03-22 13:43:44 +01:00
|
|
|
}
|
2023-03-22 16:09:33 +01:00
|
|
|
|
2023-03-25 18:48:50 +01:00
|
|
|
inline void System_BrowseForFolder(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, failedCallback, title, "", 0);
|
2023-03-22 16:09:33 +01:00
|
|
|
}
|
2023-03-22 22:07:29 +01:00
|
|
|
|
2023-06-19 23:22:44 +02:00
|
|
|
// The returned string is username + '\n' + password.
|
|
|
|
inline void System_AskUsernamePassword(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::ASK_USERNAME_PASSWORD, callback, failedCallback, title, "", 0);
|
|
|
|
}
|
|
|
|
|
2023-03-22 22:07:29 +01:00
|
|
|
inline void System_CopyStringToClipboard(const std::string &string) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, nullptr, string, "", 0);
|
2023-03-22 22:07:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void System_ExitApp() {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, nullptr, "", "", 0);
|
2023-03-22 22:07:29 +01:00
|
|
|
}
|
2023-03-22 22:17:53 +01:00
|
|
|
|
|
|
|
inline void System_RestartApp(const std::string ¶ms) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, nullptr, nullptr, params, "", 0);
|
2023-03-22 22:17:53 +01:00
|
|
|
}
|
|
|
|
|
2023-05-17 09:37:15 +02:00
|
|
|
inline void System_RecreateActivity() {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::RECREATE_ACTIVITY, nullptr, nullptr, "", "", 0);
|
|
|
|
}
|
|
|
|
|
2023-03-22 22:17:53 +01:00
|
|
|
// The design is a little weird, just a holdover from the old message. Can either toggle or set to on or off.
|
|
|
|
inline void System_ToggleFullscreenState(const std::string ¶m) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, nullptr, nullptr, param, "", 0);
|
2023-03-22 22:17:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void System_GraphicsBackendFailedAlert(const std::string ¶m) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, nullptr, param, "", 0);
|
2023-03-22 22:17:53 +01:00
|
|
|
}
|
2023-03-22 22:49:38 +01:00
|
|
|
|
|
|
|
inline void System_CameraCommand(const std::string &command) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, nullptr, nullptr, command, "", 0);
|
2023-03-22 22:49:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void System_GPSCommand(const std::string &command) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, nullptr, nullptr, command, "", 0);
|
2023-03-22 22:49:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void System_MicrophoneCommand(const std::string &command) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, nullptr, command, "", 0);
|
2023-03-22 22:49:38 +01:00
|
|
|
}
|
2023-03-22 22:55:53 +01:00
|
|
|
|
|
|
|
inline void System_ShareText(const std::string &text) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, nullptr, text, "", 0);
|
2023-03-22 22:55:53 +01:00
|
|
|
}
|
2023-03-22 23:25:00 +01:00
|
|
|
|
|
|
|
inline void System_NotifyUIState(const std::string &state) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, nullptr, nullptr, state, "", 0);
|
2023-03-22 23:25:00 +01:00
|
|
|
}
|
2023-03-24 17:40:03 +01:00
|
|
|
|
|
|
|
inline void System_SetWindowTitle(const std::string ¶m) {
|
2023-03-25 18:48:50 +01:00
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::SET_WINDOW_TITLE, nullptr, nullptr, param, "", 0);
|
2023-03-24 17:40:03 +01:00
|
|
|
}
|
2023-03-24 20:05:48 +01:00
|
|
|
|
2023-03-26 10:17:34 -07:00
|
|
|
inline bool System_SendDebugOutput(const std::string &string) {
|
|
|
|
return g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_OUTPUT, nullptr, nullptr, string, "", 0);
|
2023-03-25 17:34:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void System_SendDebugScreenshot(const std::string &data, int height) {
|
|
|
|
g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_SCREENSHOT, nullptr, nullptr, data, "", height);
|
|
|
|
}
|
|
|
|
|
2023-03-24 20:05:48 +01:00
|
|
|
// Non-inline to avoid including Path.h
|
|
|
|
void System_CreateGameShortcut(const Path &path, const std::string &title);
|
2023-08-24 13:04:41 +02:00
|
|
|
void System_ShowFileInFolder(const Path &path);
|