aboutsummaryrefslogtreecommitdiff
path: root/samples/DX_APIUsage/GfeSDKWrapper.cpp
diff options
context:
space:
mode:
authorIgor Govorov <[email protected]>2018-04-11 18:28:51 +0300
committerIgor Govorov <[email protected]>2018-04-11 18:28:51 +0300
commitc4f5a0aff93e05b3c01de0dbdc7c05e5d9530eda (patch)
tree165e3aa9f3a2fff99f70eae90e4a519e0de41a1b /samples/DX_APIUsage/GfeSDKWrapper.cpp
parentAdd Developer Content Portal documentation (diff)
downloadgfesdk-c4f5a0aff93e05b3c01de0dbdc7c05e5d9530eda.tar.xz
gfesdk-c4f5a0aff93e05b3c01de0dbdc7c05e5d9530eda.zip
Push GeForceExperience SDK 1.1.2011.1.201
Diffstat (limited to 'samples/DX_APIUsage/GfeSDKWrapper.cpp')
-rw-r--r--samples/DX_APIUsage/GfeSDKWrapper.cpp383
1 files changed, 383 insertions, 0 deletions
diff --git a/samples/DX_APIUsage/GfeSDKWrapper.cpp b/samples/DX_APIUsage/GfeSDKWrapper.cpp
new file mode 100644
index 0000000..33a4a63
--- /dev/null
+++ b/samples/DX_APIUsage/GfeSDKWrapper.cpp
@@ -0,0 +1,383 @@
+/* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+/*!
+* \file
+* Shows example usage of the GfeSDK C++ API by a directX application.
+*/
+
+#include <Windows.h>
+
+#include "GfeSDKWrapper.hpp"
+
+#include <json/json.h>
+
+char g_logBuffer[512];
+void dbgprint(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vsprintf_s(g_logBuffer, sizeof(g_logBuffer) / sizeof(g_logBuffer[0]), fmt, args);
+ printf(g_logBuffer);
+ printf("\n");
+ OutputDebugStringA(g_logBuffer);
+ OutputDebugStringA("\n");
+ va_end(args);
+}
+#define LOG(fmt, ...) dbgprint(fmt, __VA_ARGS__)
+
+static std::wstring permissionToStringW(GfeSDK::NVGSDK_Permission p)
+{
+ switch (p)
+ {
+ case GfeSDK::NVGSDK_PERMISSION_MUST_ASK: return L"Must Ask";
+ case GfeSDK::NVGSDK_PERMISSION_GRANTED: return L"Granted";
+ case GfeSDK::NVGSDK_PERMISSION_DENIED: return L"Denied";
+ default:
+ return L"UNKNOWN";
+ }
+}
+
+GfeSdkWrapper::GfeSdkWrapper() :
+ m_currentPermission(permissionToStringW(GfeSDK::NVGSDK_PERMISSION_MUST_ASK))
+{
+}
+
+void GfeSdkWrapper::Init(char const* gameName, char const* defaultLocale, GfeSDK::NVGSDK_Highlight* highlights, size_t numHighlights)
+{
+ using namespace std::placeholders;
+
+ //! [Creation CPP]
+ GfeSDK::CreateInputParams createParams;
+ createParams.appName = "gfesdk_dx_sample"; // appName will only be used/visible if GFE cannot identify your game
+ createParams.pollForCallbacks = true; // We will poll for callbacks in order to execute callbacks from game loop
+ createParams.requiredScopes = {
+ GfeSDK::NVGSDK_SCOPE_HIGHLIGHTS,
+ GfeSDK::NVGSDK_SCOPE_HIGHLIGHTS_VIDEO,
+ GfeSDK::NVGSDK_SCOPE_HIGHLIGHTS_SCREENSHOT
+ };
+ createParams.notificationCallback = std::bind(&GfeSdkWrapper::OnNotification, this, _1, _2);
+
+ GfeSDK::CreateResponse response;
+ GfeSDK::Core* gfesdkCore = GfeSDK::Core::Create(createParams, response);
+ if (GfeSDK::NVGSDK_SUCCEEDED(response.returnCode))
+ {
+ // Valid handle has been returned
+ LOG("Success: %s", GfeSDK::NVGSDK_RetCodeToString(response.returnCode));
+ LOG("PC is running GFE version %s", response.nvidiaGfeVersion.c_str());
+ LOG("PC is running GfeSDK version %d.%d", response.versionMajor, response.versionMinor);
+ switch (response.returnCode)
+ {
+ case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_GFE:
+ LOG("Compatible, but the user should update to the latest version of GFE.");
+ break;
+ case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_SDK:
+ LOG("Compatible, but this application should update to a more recent GfeSDK to get latest features/bugfixes");
+ break;
+ }
+ }
+ else
+ {
+ // No valid handle
+ LOG("Failure: %s", GfeSDK::NVGSDK_RetCodeToString(response.returnCode));
+ switch (response.returnCode)
+ {
+ case GfeSDK::NVGSDK_ERR_SDK_VERSION:
+ LOG("This version of the SDK is too old to communicate with the user's SDK. We're never planning on this happening.");
+ LOG("PC is running GFE version %s", response.nvidiaGfeVersion.c_str());
+ LOG("PC is running GfeSDK version %d.%d", response.versionMajor, response.versionMinor);
+ break;
+ case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_SDK:
+ LOG("The installed version of GFE is too old to continue. User must upgrade.");
+ LOG("PC is running GFE version %s", response.nvidiaGfeVersion.c_str());
+ LOG("PC is running GfeSDK version %d.%d", response.versionMajor, response.versionMinor);
+ break;
+ }
+ return;
+ }
+ //! [Creation CPP]
+
+ m_gfesdk.reset(gfesdkCore);
+ UpdateLastResultString(response.returnCode);
+
+ if (response.scopePermissions.find(GfeSDK::NVGSDK_SCOPE_HIGHLIGHTS_VIDEO) != response.scopePermissions.end())
+ {
+ m_currentPermission = permissionToStringW(response.scopePermissions[GfeSDK::NVGSDK_SCOPE_HIGHLIGHTS_VIDEO]);
+ }
+
+ //! [Permissions CPP]
+ // Request Permissions if user hasn't decided yet
+ GfeSDK::RequestPermissionsParams requestPermissionsParams;
+
+ // 'response' came from create call. It tells us which permissions we requested during Create,
+ // but the user hasn't yet made a decision on
+ for (auto&& entry : response.scopePermissions)
+ {
+ if (entry.second == GfeSDK::NVGSDK_PERMISSION_MUST_ASK)
+ {
+ requestPermissionsParams.scopes.push_back(entry.first);
+ }
+ }
+
+ if (!requestPermissionsParams.scopes.empty())
+ {
+ // If the user hasn't given permission for recording yet, ask them to do so now via overlay
+ m_gfesdk->RequestPermissionsAsync(requestPermissionsParams, [this, defaultLocale, highlights, numHighlights](GfeSDK::NVGSDK_RetCode rc, void* cbContext) {
+ UpdateLastResultString(rc);
+ if (GfeSDK::NVGSDK_SUCCEEDED(rc))
+ {
+ ConfigureHighlights(defaultLocale, highlights, numHighlights);
+ }
+ });
+ }
+ else
+ {
+ // Otherwise, go ahead and set up now
+ ConfigureHighlights(defaultLocale, highlights, numHighlights);
+ }
+ //! [Permissions CPP]
+}
+
+void GfeSdkWrapper::DeInit()
+{
+ // Releasing from smart pointer just to document how to delete handle
+ GfeSDK::Core* gfesdkCore = m_gfesdk.release();
+
+ //! [Release CPP]
+ delete gfesdkCore;
+ //! [Release CPP]
+}
+
+void GfeSdkWrapper::OnTick(void)
+{
+ if (!m_gfesdk) return;
+
+ // Poll for callbacks in order to execute these callbacks from the game update thread,
+ // not a third party thead owned by GfeSDK. This lets us update game state from the callbacks
+ // without causing a threading problem
+ m_gfesdk->Poll();
+}
+
+void GfeSdkWrapper::OnNotification(GfeSDK::NVGSDK_NotificationType type, GfeSDK::NotificationBase const& notification)
+{
+ switch (type)
+ {
+ case GfeSDK::NVGSDK_NOTIFICATION_PERMISSIONS_CHANGED:
+ {
+ GfeSDK::PermissionsChangedNotification const& n = static_cast<GfeSDK::PermissionsChangedNotification const&>(notification);
+
+ auto hlPermission = n.scopePermissions.find(GfeSDK::NVGSDK_SCOPE_HIGHLIGHTS_VIDEO);
+ if (hlPermission != n.scopePermissions.end())
+ {
+ m_currentPermission = permissionToStringW(hlPermission->second);
+ }
+ break;
+ }
+ case GfeSDK::NVGSDK_NOTIFICATION_OVERLAY_STATE_CHANGED:
+ {
+ GfeSDK::OverlayStateChangedNotification const& n = static_cast<GfeSDK::OverlayStateChangedNotification const&>(notification);
+
+ m_lastOverlayEvent.clear();
+ switch (n.state)
+ {
+ case GfeSDK::NVGSDK_OVERLAY_STATE_MAIN: m_lastOverlayEvent += L"Main Overlay Window"; break;
+ case GfeSDK::NVGSDK_OVERLAY_STATE_PERMISSION: m_lastOverlayEvent += L"Permission Overlay Window"; break;
+ case GfeSDK::NVGSDK_OVERLAY_STATE_HIGHLIGHTS_SUMMARY: m_lastOverlayEvent += L"Highlights Summary Overlay Window"; break;
+ default:
+ m_lastOverlayEvent += L"UNKNOWNWindow";
+ }
+ m_lastOverlayEvent += (n.open ? L" OPEN" : L" CLOSE");
+ break;
+ }
+ }
+}
+
+void GfeSdkWrapper::OnOpenGroup(std::string const& id)
+{
+ if (!m_highlights) return;
+
+ //! [OpenGroup CPP]
+ GfeSDK::HighlightOpenGroupParams params;
+ params.groupId = id;
+ params.groupDescriptionLocaleTable["en-US"] = id;
+ m_highlights->OpenGroupAsync(params, [this](GfeSDK::NVGSDK_RetCode rc, void*) {
+ UpdateLastResultString(rc);
+ });
+ //! [OpenGroup CPP]
+}
+
+void GfeSdkWrapper::OnCloseGroup(std::string const& id, bool destroy)
+{
+ if (!m_highlights) return;
+
+ //! [CloseGroup CPP]
+ GfeSDK::HighlightCloseGroupParams params;
+ params.groupId = id;
+ params.destroyHighlights = destroy;
+ m_highlights->CloseGroupAsync(params, [this](GfeSDK::NVGSDK_RetCode rc, void*) {
+ UpdateLastResultString(rc);
+ });
+ //! [CloseGroup CPP]
+
+#ifdef DOXYGEN
+ //! [Async Call No Callback]
+ // If the caller doesn't care about the return value, no need to pass callbacks
+ GfeSDK::HighlightCloseGroupParams params = { "GROUP_1" };
+ m_highlights->CloseGroupAsync(params);
+ //! [Async Call No Callback]
+#endif
+}
+
+void GfeSdkWrapper::OnSaveScreenshot(std::string const& highlightId, std::string const& groupId)
+{
+ GfeSDK::ScreenshotHighlightParams params;
+ params.groupId = groupId;
+ params.highlightId = highlightId;
+ m_highlights->SetScreenshotHighlightAsync(params, [this](GfeSDK::NVGSDK_RetCode rc, void*) {
+ UpdateLastResultString(rc);
+ });
+}
+
+void GfeSdkWrapper::OnSaveVideo(std::string const& highlightId, std::string const& groupId, int startDelta, int endDelta)
+{
+ //! [SaveVideo CPP]
+ GfeSDK::VideoHighlightParams params;
+ params.startDelta = startDelta;
+ params.endDelta = endDelta;
+ params.groupId = groupId;
+ params.highlightId = highlightId;
+ m_highlights->SetVideoHighlightAsync(params, [this](GfeSDK::NVGSDK_RetCode rc, void*) {
+ UpdateLastResultString(rc);
+ });
+ //! [SaveVideo CPP]
+}
+
+void GfeSdkWrapper::OnGetNumHighlights(std::string const& groupId, GfeSDK::NVGSDK_HighlightSignificance sigFilter, GfeSDK::NVGSDK_HighlightType tagFilter)
+{
+ GfeSDK::GroupView v;
+ v.groupId = groupId;
+ v.significanceFilter = sigFilter;
+ v.tagsFilter = tagFilter;
+
+ m_highlights->GetNumberOfHighlightsAsync(v, [this](GfeSDK::NVGSDK_RetCode rc, GfeSDK::GetNumberOfHighlightsResponse const* response, void*) {
+ UpdateLastResultString(rc);
+ if (GfeSDK::NVGSDK_SUCCEEDED(rc))
+ {
+ m_lastQueryResult = std::to_wstring(response->numHighlights);
+ }
+ });
+}
+
+void GfeSdkWrapper::OnOpenSummary(char const* groupIds[], size_t numGroups, GfeSDK::NVGSDK_HighlightSignificance sigFilter, GfeSDK::NVGSDK_HighlightType tagFilter)
+{
+ //! [OpenSummary CPP]
+ GfeSDK::SummaryParams params;
+
+ // Can show more than one group at a time, each with their own filters if desired
+ for (size_t i = 0; i < numGroups; ++i)
+ {
+ GfeSDK::GroupView v;
+ v.groupId = groupIds[i];
+ v.significanceFilter = sigFilter;
+ v.tagsFilter = tagFilter;
+ params.groupViews.push_back(v);
+ }
+
+ m_highlights->OpenSummaryAsync(params, [this](GfeSDK::NVGSDK_RetCode rc, void*) {
+ UpdateLastResultString(rc);
+ });
+ //! [OpenSummary CPP]
+}
+
+void GfeSdkWrapper::OnRequestLanguage(void)
+{
+ //! [Asynchonous Call]
+ // We are passing two arguments to this function, the function lambda, and a user context. In this case, we're passing
+ // the 'this' pointer as the user context. This gets passed through unmodified for use in the callback function.
+ m_gfesdk->GetUILanguageAsync([this](GfeSDK::NVGSDK_RetCode rc, GfeSDK::GetUILanguageResponse const* response, void* context) {
+ // Passed this pointer through as context
+ GfeSdkWrapper* thiz = reinterpret_cast<GfeSdkWrapper*>(context);
+
+ UpdateLastResultString(rc);
+ if (GfeSDK::NVGSDK_SUCCEEDED(rc))
+ {
+ m_lastQueryResult = m_converter.from_bytes(response->cultureCode);
+ }
+ }, this);
+ //! [Asynchonous Call]
+}
+
+void GfeSdkWrapper::OnRequestUserSettings(void)
+{
+ m_highlights->GetUserSettingsAsync([this](GfeSDK::NVGSDK_RetCode rc, GfeSDK::GetUserSettingsResponse const* response, void*) {
+ UpdateLastResultString(rc);
+ m_lastQueryResult = L"";
+ if (GfeSDK::NVGSDK_SUCCEEDED(rc))
+ {
+ for (auto it = response->highlightSettings.begin(); it != response->highlightSettings.end(); ++it)
+ {
+ m_lastQueryResult += L"\n" + m_converter.from_bytes(it->highlightId) + (it->enabled ? L": ON" : L": OFF");
+ }
+ }
+ });
+}
+
+wchar_t const* GfeSdkWrapper::GetCurrentPermissionStr(void)
+{
+ return m_currentPermission.c_str();
+}
+
+wchar_t const* GfeSdkWrapper::GetLastOverlayEvent(void)
+{
+ return m_lastOverlayEvent.c_str();
+}
+
+wchar_t const* GfeSdkWrapper::GetLastResult(void)
+{
+ return m_lastResult.c_str();
+}
+
+wchar_t const* GfeSdkWrapper::GetLastQueryResult(void)
+{
+ return m_lastQueryResult.c_str();
+}
+
+void GfeSdkWrapper::ConfigureHighlights(char const* defaultLocale, GfeSDK::NVGSDK_Highlight* highlights, size_t numHighlights)
+{
+ //! [ConfigureHighlights CPP]
+ // Create handle to highlights module
+ m_highlights.reset(GfeSDK::Highlights::Create(m_gfesdk.get()));
+
+ GfeSDK::HighlightConfigParams configParams;
+ configParams.defaultLocale = defaultLocale;
+
+ // Set up highlight definition table
+ for (size_t i = 0; i < numHighlights; ++i)
+ {
+ GfeSDK::HighlightDefinition highlightDef;
+ highlightDef.id = highlights[i].id;
+ highlightDef.userDefaultInterest = highlights[i].userInterest;
+ highlightDef.significance = highlights[i].significance;
+ highlightDef.highlightTags = highlights[i].highlightTags;
+ for (size_t j = 0; j < highlights[i].nameTableSize; ++j)
+ {
+ highlightDef.nameLocaleTable[highlights[i].nameTable[j].localeCode] = highlights[i].nameTable[j].localizedString;
+ }
+
+ configParams.highlightDefinitions.push_back(highlightDef);
+ }
+
+ m_highlights->ConfigureAsync(configParams, [this](GfeSDK::NVGSDK_RetCode rc, void*) {
+ UpdateLastResultString(rc);
+ });
+ //! [ConfigureHighlights CPP]
+}
+
+void GfeSdkWrapper::UpdateLastResultString(GfeSDK::NVGSDK_RetCode rc)
+{
+ m_lastResult = m_converter.from_bytes(GfeSDK::RetCodeToString(rc));
+}