mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
RequestManager: Add a separate callback for failures. Separate because we usually don't need it, except Osk.
This commit is contained in:
parent
659b51e55a
commit
221d2f7eb5
@ -15,16 +15,16 @@ const char *RequestTypeAsString(SystemRequestType type) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2, int param3) {
|
||||
bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, RequestFailedCallback failedCallback, const std::string ¶m1, const std::string ¶m2, int param3) {
|
||||
int requestId = idCounter_++;
|
||||
|
||||
// NOTE: We need to register immediately, in order to support synchronous implementations.
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(callbackMutex_);
|
||||
callbackMap_[requestId] = callback;
|
||||
callbackMap_[requestId] = { callback, failedCallback };
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "Making system request %s: id %d, callback_valid %d", RequestTypeAsString(type), requestId, callback != nullptr);
|
||||
INFO_LOG(SYSTEM, "Making system request %s: id %d", RequestTypeAsString(type), requestId);
|
||||
if (!System_MakeRequest(type, requestId, param1, param2, param3)) {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(callbackMutex_);
|
||||
@ -45,12 +45,13 @@ void RequestManager::PostSystemSuccess(int requestId, const char *responseString
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> responseGuard(responseMutex_);
|
||||
PendingResponse response;
|
||||
response.callback = iter->second;
|
||||
PendingSuccess response;
|
||||
response.callback = iter->second.callback;
|
||||
response.responseString = responseString;
|
||||
response.responseValue = responseValue;
|
||||
pendingResponses_.push_back(response);
|
||||
pendingSuccesses_.push_back(response);
|
||||
INFO_LOG(SYSTEM, "PostSystemSuccess: Request %d (%s, %d)", requestId, responseString, responseValue);
|
||||
callbackMap_.erase(iter);
|
||||
}
|
||||
|
||||
void RequestManager::PostSystemFailure(int requestId) {
|
||||
@ -60,28 +61,41 @@ void RequestManager::PostSystemFailure(int requestId) {
|
||||
ERROR_LOG(SYSTEM, "PostSystemFailure: Unexpected request ID %d", requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "PostSystemFailure: Request %d failed", requestId);
|
||||
|
||||
std::lock_guard<std::mutex> responseGuard(responseMutex_);
|
||||
PendingFailure response;
|
||||
response.callback = iter->second.failedCallback;
|
||||
pendingFailures_.push_back(response);
|
||||
callbackMap_.erase(iter);
|
||||
}
|
||||
|
||||
void RequestManager::ProcessRequests() {
|
||||
std::lock_guard<std::mutex> guard(responseMutex_);
|
||||
for (auto &iter : pendingResponses_) {
|
||||
for (auto &iter : pendingSuccesses_) {
|
||||
if (iter.callback) {
|
||||
iter.callback(iter.responseString.c_str(), iter.responseValue);
|
||||
}
|
||||
}
|
||||
pendingResponses_.clear();
|
||||
pendingSuccesses_.clear();
|
||||
for (auto &iter : pendingFailures_) {
|
||||
if (iter.callback) {
|
||||
iter.callback();
|
||||
}
|
||||
}
|
||||
pendingFailures_.clear();
|
||||
}
|
||||
|
||||
void RequestManager::Clear() {
|
||||
std::lock_guard<std::mutex> guard(callbackMutex_);
|
||||
std::lock_guard<std::mutex> responseGuard(responseMutex_);
|
||||
|
||||
pendingResponses_.clear();
|
||||
pendingSuccesses_.clear();
|
||||
pendingFailures_.clear();
|
||||
callbackMap_.clear();
|
||||
}
|
||||
|
||||
void System_CreateGameShortcut(const Path &path, const std::string &title) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::CREATE_GAME_SHORTCUT, nullptr, path.ToString(), title, 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::CREATE_GAME_SHORTCUT, nullptr, nullptr, path.ToString(), title, 0);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
class Path;
|
||||
|
||||
typedef std::function<void(const char *responseString, int responseValue)> RequestCallback;
|
||||
typedef std::function<void()> RequestFailedCallback;
|
||||
|
||||
// Platforms often have to process requests asynchronously, on wildly different threads.
|
||||
// (Especially Android...)
|
||||
@ -18,7 +19,9 @@ 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.
|
||||
bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2, int param3);
|
||||
// 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);
|
||||
|
||||
// Called by the platform implementation, when it's finished with a request.
|
||||
void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0);
|
||||
@ -35,19 +38,30 @@ private:
|
||||
struct PendingRequest {
|
||||
SystemRequestType type;
|
||||
RequestCallback callback;
|
||||
RequestFailedCallback failedCallback;
|
||||
};
|
||||
|
||||
std::map<int, RequestCallback> callbackMap_;
|
||||
struct CallbackPair {
|
||||
RequestCallback callback;
|
||||
RequestFailedCallback failedCallback;
|
||||
};
|
||||
|
||||
std::map<int, CallbackPair> callbackMap_;
|
||||
std::mutex callbackMutex_;
|
||||
|
||||
struct PendingResponse {
|
||||
struct PendingSuccess {
|
||||
std::string responseString;
|
||||
int responseValue;
|
||||
RequestCallback callback;
|
||||
};
|
||||
|
||||
struct PendingFailure {
|
||||
RequestFailedCallback callback;
|
||||
};
|
||||
|
||||
int idCounter_ = 0;
|
||||
std::vector<PendingResponse> pendingResponses_;
|
||||
std::vector<PendingSuccess> pendingSuccesses_;
|
||||
std::vector<PendingFailure> pendingFailures_;
|
||||
std::mutex responseMutex_;
|
||||
};
|
||||
|
||||
@ -57,14 +71,14 @@ extern RequestManager g_requestManager;
|
||||
|
||||
// Wrappers for easy requests.
|
||||
// NOTE: Semantics have changed - this no longer calls the callback on cancellation.
|
||||
inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
// This one will pop up a special image brwoser if available. You can also pick
|
||||
// images with the file browser below.
|
||||
inline void System_BrowseForImage(const std::string &title, RequestCallback callback) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, title, "", 0);
|
||||
inline void System_BrowseForImage(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, failedCallback, title, "", 0);
|
||||
}
|
||||
|
||||
enum class BrowseFileType {
|
||||
@ -75,57 +89,57 @@ enum class BrowseFileType {
|
||||
ANY,
|
||||
};
|
||||
|
||||
inline void System_BrowseForFile(const std::string &title, BrowseFileType type, RequestCallback callback) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, callback, title, "", (int)type);
|
||||
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);
|
||||
}
|
||||
|
||||
inline void System_BrowseForFolder(const std::string &title, RequestCallback callback) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, title, "", 0);
|
||||
inline void System_BrowseForFolder(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, failedCallback, title, "", 0);
|
||||
}
|
||||
|
||||
inline void System_CopyStringToClipboard(const std::string &string) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, string, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, nullptr, string, "", 0);
|
||||
}
|
||||
|
||||
inline void System_ExitApp() {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, "", "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, nullptr, "", "", 0);
|
||||
}
|
||||
|
||||
inline void System_RestartApp(const std::string ¶ms) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, nullptr, params, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, nullptr, nullptr, params, "", 0);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, nullptr, param, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, nullptr, nullptr, param, "", 0);
|
||||
}
|
||||
|
||||
inline void System_GraphicsBackendFailedAlert(const std::string ¶m) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, param, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, nullptr, param, "", 0);
|
||||
}
|
||||
|
||||
inline void System_CameraCommand(const std::string &command) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, nullptr, command, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, nullptr, nullptr, command, "", 0);
|
||||
}
|
||||
|
||||
inline void System_GPSCommand(const std::string &command) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, nullptr, command, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, nullptr, nullptr, command, "", 0);
|
||||
}
|
||||
|
||||
inline void System_MicrophoneCommand(const std::string &command) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, command, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, nullptr, command, "", 0);
|
||||
}
|
||||
|
||||
inline void System_ShareText(const std::string &text) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, text, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, nullptr, text, "", 0);
|
||||
}
|
||||
|
||||
inline void System_NotifyUIState(const std::string &state) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, nullptr, state, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, nullptr, nullptr, state, "", 0);
|
||||
}
|
||||
|
||||
inline void System_SetWindowTitle(const std::string ¶m) {
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::SET_WINDOW_TITLE, nullptr, param, "", 0);
|
||||
g_requestManager.MakeSystemRequest(SystemRequestType::SET_WINDOW_TITLE, nullptr, nullptr, param, "", 0);
|
||||
}
|
||||
|
||||
// Non-inline to avoid including Path.h
|
||||
|
@ -892,15 +892,26 @@ int PSPOskDialog::NativeKeyboard() {
|
||||
defaultText.assign(u"VALUE");
|
||||
|
||||
// There's already ConvertUCS2ToUTF8 in this file. Should we use that instead of the global ones?
|
||||
System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), [&](const std::string &value, int iValue) {
|
||||
std::lock_guard<std::mutex> guard(nativeMutex_);
|
||||
if (nativeStatus_ != PSPOskNativeStatus::WAITING) {
|
||||
return;
|
||||
System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText),
|
||||
[&](const std::string &value, int) {
|
||||
// Success callback
|
||||
std::lock_guard<std::mutex> guard(nativeMutex_);
|
||||
if (nativeStatus_ != PSPOskNativeStatus::WAITING) {
|
||||
return;
|
||||
}
|
||||
nativeValue_ = value;
|
||||
nativeStatus_ = PSPOskNativeStatus::SUCCESS;
|
||||
},
|
||||
[&]() {
|
||||
// Failure callback
|
||||
std::lock_guard<std::mutex> guard(nativeMutex_);
|
||||
if (nativeStatus_ != PSPOskNativeStatus::WAITING) {
|
||||
return;
|
||||
}
|
||||
nativeValue_ = "";
|
||||
nativeStatus_ = PSPOskNativeStatus::FAILURE;
|
||||
}
|
||||
|
||||
nativeValue_ = value;
|
||||
nativeStatus_ = iValue ? PSPOskNativeStatus::SUCCESS : PSPOskNativeStatus::FAILURE;
|
||||
});
|
||||
);
|
||||
} else if (nativeStatus_ == PSPOskNativeStatus::SUCCESS) {
|
||||
inputChars = ConvertUTF8ToUCS2(nativeValue_);
|
||||
nativeValue_.clear();
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 77551c429f86c0e077f26552b7c1c0f12a9f235e
|
||||
Subproject commit b34f619e1c85810dcb3c578107d2e48ba4ee2b37
|
Loading…
Reference in New Issue
Block a user