Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c7df02941 | ||
|
|
c63c5100e2 | ||
|
|
bf05088d70 | ||
|
|
e7bb146f92 | ||
|
|
688c4a90d9 | ||
|
|
165ad96be1 | ||
|
|
115ced7ab4 | ||
|
|
ef15b5641a | ||
|
|
be50464619 | ||
|
|
d847b71c86 | ||
|
|
dfcc1ff899 | ||
|
|
65562937f3 | ||
|
|
7b5dc33a21 | ||
|
|
f64c13b9ec | ||
|
|
25f70e570e | ||
|
|
b27b64c25c | ||
|
|
bfc64c926a | ||
|
|
88ad983aa4 | ||
|
|
a95d2e76f5 | ||
|
|
037886ba5b | ||
|
|
011edfe2a0 | ||
|
|
1a5a6773ce | ||
|
|
dda22fd387 | ||
|
|
7254224347 | ||
|
|
789e52af57 | ||
|
|
b2fcd6c084 | ||
|
|
76e5794203 | ||
|
|
a81332dd23 | ||
|
|
e1fab22d98 | ||
|
|
cb5e58d465 | ||
|
|
eaeb9ec6f7 | ||
|
|
88bb17fca8 | ||
|
|
f672b8534f | ||
|
|
839c0a45a0 | ||
|
|
974e44ba4c | ||
|
|
9461ebec2d | ||
|
|
48d8a53cd6 | ||
|
|
2a8dfd63da | ||
|
|
49ac431792 | ||
|
|
8a7c463c52 | ||
|
|
eab77fba7a | ||
|
|
61d90a5a88 | ||
|
|
ef99f02bc7 | ||
|
|
9166a604d6 | ||
|
|
d5a1189053 | ||
|
|
cb52a53922 | ||
|
|
1aff2ff0c3 | ||
|
|
fd63aad3b8 | ||
|
|
9a807a0685 | ||
|
|
40fc9fa26f | ||
|
|
cf0d29d452 | ||
|
|
e411c207ae | ||
|
|
5df2704ccc | ||
|
|
36f468a599 | ||
|
|
dfae69834a | ||
|
|
e53b32fa57 | ||
|
|
969afac696 | ||
|
|
50d4f267ba | ||
|
|
33b9caaca9 | ||
|
|
4f84843b00 | ||
|
|
44f415f94d |
+4
-1
@@ -9,4 +9,7 @@
|
||||
url = https://github.com/gabomdq/SDL_GameControllerDB.git
|
||||
[submodule "soundio/libsoundio"]
|
||||
path = soundio/libsoundio
|
||||
url = https://github.com/andrewrk/libsoundio.git
|
||||
url = https://github.com/cgutman/libsoundio.git
|
||||
[submodule "h264bitstream/h264bitstream"]
|
||||
path = h264bitstream/h264bitstream
|
||||
url = https://github.com/aizvorski/h264bitstream.git
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
QT -= core gui
|
||||
|
||||
TARGET = AntiHooking
|
||||
TEMPLATE = lib
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
# Ensure symbols are always generated
|
||||
CONFIG += force_debug_info
|
||||
|
||||
INCLUDEPATH += $$PWD/../libs/windows/include
|
||||
contains(QT_ARCH, i386) {
|
||||
LIBS += -L$$PWD/../libs/windows/lib/x86
|
||||
}
|
||||
contains(QT_ARCH, x86_64) {
|
||||
LIBS += -L$$PWD/../libs/windows/lib/x64
|
||||
}
|
||||
|
||||
LIBS += -lNktHookLib
|
||||
DEFINES += ANTIHOOKING_LIBRARY
|
||||
SOURCES += antihookingprotection.cpp
|
||||
HEADERS += antihookingprotection.h
|
||||
@@ -0,0 +1,161 @@
|
||||
#include "antihookingprotection.h"
|
||||
|
||||
#include <NktHookLib.h>
|
||||
|
||||
typedef HMODULE (WINAPI *LoadLibraryAFunc)(LPCSTR lpLibFileName);
|
||||
typedef HMODULE (WINAPI *LoadLibraryWFunc)(LPCWSTR lpLibFileName);
|
||||
typedef HMODULE (WINAPI *LoadLibraryExAFunc)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
||||
typedef HMODULE (WINAPI *LoadLibraryExWFunc)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
||||
|
||||
class AntiHookingProtection
|
||||
{
|
||||
public:
|
||||
static void enable()
|
||||
{
|
||||
#ifdef QT_DEBUG
|
||||
s_HookManager.SetEnableDebugOutput(true);
|
||||
#endif
|
||||
|
||||
HINSTANCE kernel32Handle = NktHookLibHelpers::GetModuleBaseAddress(L"kernel32.dll");
|
||||
SIZE_T hookId;
|
||||
|
||||
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryA,
|
||||
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryA"),
|
||||
(LPVOID)AntiHookingProtection::LoadLibraryAHook);
|
||||
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryW,
|
||||
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryW"),
|
||||
(LPVOID)AntiHookingProtection::LoadLibraryWHook);
|
||||
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryExA,
|
||||
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryExA"),
|
||||
(LPVOID)AntiHookingProtection::LoadLibraryExAHook);
|
||||
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryExW,
|
||||
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryExW"),
|
||||
(LPVOID)AntiHookingProtection::LoadLibraryExWHook);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool isImageBlacklistedW(LPCWSTR lpLibFileName)
|
||||
{
|
||||
LPCWSTR dllName;
|
||||
|
||||
// If the library has a path prefixed, remove it
|
||||
dllName = wcsrchr(lpLibFileName, '\\');
|
||||
if (!dllName) {
|
||||
// No prefix, so use the full name
|
||||
dllName = lpLibFileName;
|
||||
}
|
||||
else {
|
||||
// Advance past the backslash
|
||||
dllName++;
|
||||
}
|
||||
|
||||
// FIXME: We don't currently handle LoadLibrary calls where the
|
||||
// library name does not include a file extension and the loader
|
||||
// automatically assumes .dll.
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(k_BlacklistedDlls); i++) {
|
||||
if (_wcsicmp(dllName, k_BlacklistedDlls[i]) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isImageBlacklistedA(LPCSTR lpLibFileName)
|
||||
{
|
||||
int uniChars = MultiByteToWideChar(CP_THREAD_ACP, 0, lpLibFileName, -1, nullptr, 0);
|
||||
if (uniChars > 0) {
|
||||
PWCHAR wideBuffer = new WCHAR[uniChars];
|
||||
uniChars = MultiByteToWideChar(CP_THREAD_ACP, 0,
|
||||
lpLibFileName, -1,
|
||||
wideBuffer, uniChars * sizeof(WCHAR));
|
||||
if (uniChars > 0) {
|
||||
bool ret = isImageBlacklistedW(wideBuffer);
|
||||
delete[] wideBuffer;
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
delete[] wideBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
// Error path
|
||||
return false;
|
||||
}
|
||||
|
||||
static HMODULE WINAPI LoadLibraryAHook(LPCSTR lpLibFileName)
|
||||
{
|
||||
if (lpLibFileName && isImageBlacklistedA(lpLibFileName)) {
|
||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return s_RealLoadLibraryA(lpLibFileName);
|
||||
}
|
||||
|
||||
static HMODULE WINAPI LoadLibraryWHook(LPCWSTR lpLibFileName)
|
||||
{
|
||||
if (lpLibFileName && isImageBlacklistedW(lpLibFileName)) {
|
||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return s_RealLoadLibraryW(lpLibFileName);
|
||||
}
|
||||
|
||||
static HMODULE WINAPI LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
||||
{
|
||||
if (lpLibFileName && isImageBlacklistedA(lpLibFileName)) {
|
||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return s_RealLoadLibraryExA(lpLibFileName, hFile, dwFlags);
|
||||
}
|
||||
|
||||
static HMODULE WINAPI LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
||||
{
|
||||
if (lpLibFileName && isImageBlacklistedW(lpLibFileName)) {
|
||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return s_RealLoadLibraryExW(lpLibFileName, hFile, dwFlags);
|
||||
}
|
||||
|
||||
static CNktHookLib s_HookManager;
|
||||
static LoadLibraryAFunc s_RealLoadLibraryA;
|
||||
static LoadLibraryWFunc s_RealLoadLibraryW;
|
||||
static LoadLibraryExAFunc s_RealLoadLibraryExA;
|
||||
static LoadLibraryExWFunc s_RealLoadLibraryExW;
|
||||
|
||||
static constexpr LPCWSTR k_BlacklistedDlls[] = {
|
||||
// This DLL shipped with ASUS Sonic Radar 3 improperly handles
|
||||
// D3D9 exclusive fullscreen in a way that causes CreateDeviceEx()
|
||||
// to deadlock. https://github.com/moonlight-stream/moonlight-qt/issues/102
|
||||
L"NahimicOSD.dll"
|
||||
};
|
||||
};
|
||||
|
||||
CNktHookLib AntiHookingProtection::s_HookManager;
|
||||
LoadLibraryAFunc AntiHookingProtection::s_RealLoadLibraryA;
|
||||
LoadLibraryWFunc AntiHookingProtection::s_RealLoadLibraryW;
|
||||
LoadLibraryExAFunc AntiHookingProtection::s_RealLoadLibraryExA;
|
||||
LoadLibraryExWFunc AntiHookingProtection::s_RealLoadLibraryExW;
|
||||
|
||||
AH_EXPORT void AntiHookingDummyImport() {}
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
AntiHookingProtection::enable();
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef ANTIHOOKING_LIBRARY
|
||||
#define AH_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define AH_EXPORT extern "C" __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
AH_EXPORT void AntiHookingDummyImport();
|
||||
|
||||
+2
-2
@@ -23,9 +23,9 @@
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.6.0</string>
|
||||
<string>0.6.4</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.0</string>
|
||||
<string>0.6.4</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Moonlight</string>
|
||||
</dict>
|
||||
|
||||
+25
-4
@@ -18,7 +18,9 @@ CONFIG += force_debug_info
|
||||
# Since this binds the app against the Qt runtime version, we will only
|
||||
# do this for Windows and Mac, since they ship with the Qt runtime.
|
||||
win32|macx {
|
||||
CONFIG += qtquickcompiler
|
||||
CONFIG(release, debug|release) {
|
||||
CONFIG += qtquickcompiler
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE = app
|
||||
@@ -258,6 +260,19 @@ else:unix: LIBS += -L$$OUT_PWD/../soundio/ -lsoundio
|
||||
INCLUDEPATH += $$PWD/../soundio/libsoundio
|
||||
DEPENDPATH += $$PWD/../soundio/libsoundio
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../h264bitstream/release/ -lh264bitstream
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../h264bitstream/debug/ -lh264bitstream
|
||||
else:unix: LIBS += -L$$OUT_PWD/../h264bitstream/ -lh264bitstream
|
||||
|
||||
INCLUDEPATH += $$PWD/../h264bitstream/h264bitstream
|
||||
DEPENDPATH += $$PWD/../h264bitstream/h264bitstream
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/release/ -lAntiHooking
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/debug/ -lAntiHooking
|
||||
|
||||
INCLUDEPATH += $$PWD/../AntiHooking
|
||||
DEPENDPATH += $$PWD/../AntiHooking
|
||||
|
||||
unix:!macx: {
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX = /usr/local
|
||||
@@ -299,8 +314,14 @@ macx {
|
||||
|
||||
APP_BUNDLE_RESOURCES.files = moonlight.icns SDL_GameControllerDB/gamecontrollerdb.txt
|
||||
APP_BUNDLE_RESOURCES.path = Contents/Resources
|
||||
QMAKE_BUNDLE_DATA += APP_BUNDLE_RESOURCES
|
||||
|
||||
APP_BUNDLE_FRAMEWORKS.files = $$files(../libs/mac/Frameworks/*.framework, true)
|
||||
APP_BUNDLE_FRAMEWORKS.path = Contents/Frameworks
|
||||
|
||||
QMAKE_BUNDLE_DATA += APP_BUNDLE_RESOURCES APP_BUNDLE_FRAMEWORKS
|
||||
|
||||
QMAKE_RPATHDIR += @executable_path/../Frameworks
|
||||
}
|
||||
|
||||
VERSION = 0.6.0
|
||||
DEFINES += VERSION_STR=\\\"0.6.0\\\"
|
||||
VERSION = 0.6.4
|
||||
DEFINES += VERSION_STR=\\\"0.6.4\\\"
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#include "nvhttp.h"
|
||||
#include "settings/streamingpreferences.h"
|
||||
|
||||
#include <Limelight.h>
|
||||
#include <QtEndian>
|
||||
|
||||
#include <QThread>
|
||||
#include <QThreadPool>
|
||||
|
||||
@@ -573,6 +576,16 @@ private:
|
||||
// Update addresses depending on the context
|
||||
if (m_Mdns) {
|
||||
newComputer->localAddress = m_Address;
|
||||
|
||||
// Get the WAN IP address using STUN if we're on mDNS
|
||||
quint32 addr;
|
||||
int err = LiFindExternalAddressIP4("stun.stunprotocol.org", 3478, &addr);
|
||||
if (err == 0) {
|
||||
newComputer->remoteAddress = QHostAddress(qFromBigEndian(addr)).toString();
|
||||
}
|
||||
else {
|
||||
qWarning() << "STUN failed to get WAN address:" << err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
newComputer->manualAddress = m_Address;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <QSslKey>
|
||||
#include <QImageReader>
|
||||
#include <QtEndian>
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#define REQUEST_TIMEOUT_MS 5000
|
||||
|
||||
@@ -24,6 +25,10 @@ NvHTTP::NvHTTP(QString address) :
|
||||
m_BaseUrlHttps.setHost(address);
|
||||
m_BaseUrlHttp.setPort(47989);
|
||||
m_BaseUrlHttps.setPort(47984);
|
||||
|
||||
// Never use a proxy server
|
||||
QNetworkProxy noProxy(QNetworkProxy::NoProxy);
|
||||
m_Nam.setProxy(noProxy);
|
||||
}
|
||||
|
||||
QVector<int>
|
||||
|
||||
@@ -33,6 +33,63 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="0.6.4" date="2018-11-20">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
<ul>
|
||||
<li>Added an option to match client display refresh rate when FPS is unlocked</li>
|
||||
</ul>
|
||||
<p>Bugfixes:</p>
|
||||
<ul>
|
||||
<li>Fixed multiple gamepads not being detected on the host in some scenarios</li>
|
||||
<li>Fixed an incorrect warning when trying to stream at 4K</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.6.3" date="2018-11-16">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
<ul>
|
||||
<li>Added support for GeForce Experience 3.16</li>
|
||||
<li>Added an option to force Moonlight to start in windowed mode</li>
|
||||
</ul>
|
||||
<p>Bugfixes:</p>
|
||||
<ul>
|
||||
<li>Fixed scrolling not working on the settings page</li>
|
||||
<li>Skipped using proxy servers when attempting to stream</li>
|
||||
<li>Fixed a couple possible crashes</li>
|
||||
<li>Renamed the mouse acceleration option to be more clear</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.6.2" date="2018-10-28">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
<ul>
|
||||
<li>Added automatic IP address detection for Internet streaming</li>
|
||||
<li>Added a quit shortcut tip for gamepad users</li>
|
||||
</ul>
|
||||
<p>Bugfixes:</p>
|
||||
<ul>
|
||||
<li>Fixed server state polling not being stopped while streaming</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.6.1" date="2018-10-14">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
<ul>
|
||||
<li>Added support for quitting Moonlight via gamepad</li>
|
||||
<li>Added tooltips for games with very long names</li>
|
||||
</ul>
|
||||
<p>Bugfixes:</p>
|
||||
<ul>
|
||||
<li>Added a workaround for a memory leak in the VAAPI driver for AMD GPUs</li>
|
||||
<li>Fixed combo boxes on the settings page being too small for certain DPI scaling</li>
|
||||
<li>Reduced power usage when Moonlight is idling in the background for a while</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.6.0" date="2018-10-06">
|
||||
<description>
|
||||
<p>New features:</p>
|
||||
|
||||
@@ -100,6 +100,12 @@ GridView {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
elide: Text.ElideRight
|
||||
|
||||
// Display a tooltip with the full name if it's truncated
|
||||
ToolTip.text: model.name
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: (parent.hovered || parent.highlighted) && truncated
|
||||
}
|
||||
|
||||
function launchOrResumeSelectedApp()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import QtQuick 2.11
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
// https://stackoverflow.com/questions/45029968/how-do-i-set-the-combobox-width-to-fit-the-largest-item
|
||||
@@ -9,17 +9,17 @@ ComboBox {
|
||||
|
||||
TextMetrics {
|
||||
id: popupMetrics
|
||||
font: popup.font
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetrics
|
||||
font: parent.font
|
||||
}
|
||||
|
||||
// We call this every time the options change (and init)
|
||||
// so we can adjust the combo box width here too
|
||||
onActivated: {
|
||||
textMetrics.font = font
|
||||
popupMetrics.font = popup.font
|
||||
textWidth = 0
|
||||
for (var i = 0; i < count; i++){
|
||||
textMetrics.text = textAt(i)
|
||||
|
||||
+74
-11
@@ -5,9 +5,24 @@ import StreamingPreferences 1.0
|
||||
import ComputerManager 1.0
|
||||
import SdlGamepadKeyNavigation 1.0
|
||||
|
||||
ScrollView {
|
||||
Flickable {
|
||||
id: settingsPage
|
||||
objectName: "Settings"
|
||||
anchors.fill: parent
|
||||
|
||||
contentWidth: settingsColumn1.width > settingsColumn2.width ? settingsColumn1.width : settingsColumn2.width
|
||||
contentHeight: settingsColumn1.height > settingsColumn2.height ? settingsColumn1.height : settingsColumn2.height
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
parent: settingsPage.parent
|
||||
anchors {
|
||||
top: settingsPage.top
|
||||
left: settingsPage.right
|
||||
bottom: settingsPage.bottom
|
||||
|
||||
leftMargin: -10
|
||||
}
|
||||
}
|
||||
|
||||
StreamingPreferences {
|
||||
id: prefs
|
||||
@@ -64,7 +79,7 @@ ScrollView {
|
||||
Label {
|
||||
width: parent.width
|
||||
id: resFPSdesc
|
||||
text: qsTr("Setting values too high for your PC may cause lag, stuttering, or errors.")
|
||||
text: qsTr("Setting values too high for your PC or network connection may cause lag, stuttering, or errors.")
|
||||
font.pointSize: 9
|
||||
wrapMode: Text.Wrap
|
||||
color: "white"
|
||||
@@ -211,7 +226,16 @@ ScrollView {
|
||||
// Use 64 as the cutoff for adding a separate option to
|
||||
// handle wonky displays that report just over 60 Hz.
|
||||
if (max_fps > 64) {
|
||||
fpsListModel.append({"text": max_fps+" FPS", "video_fps": ""+max_fps})
|
||||
// Mark any FPS value greater than 120 as unsupported
|
||||
if (prefs.unsupportedFps && max_fps > 120) {
|
||||
fpsListModel.append({"text": max_fps+" FPS (Unsupported)", "video_fps": ""+max_fps})
|
||||
}
|
||||
else if (max_fps > 120) {
|
||||
fpsListModel.append({"text": "120 FPS", "video_fps": "120"})
|
||||
}
|
||||
else {
|
||||
fpsListModel.append({"text": max_fps+" FPS", "video_fps": ""+max_fps})
|
||||
}
|
||||
}
|
||||
|
||||
// Add unsupported FPS values that come after the display max FPS
|
||||
@@ -329,6 +353,7 @@ ScrollView {
|
||||
}
|
||||
|
||||
id: windowModeComboBox
|
||||
hoverEnabled: true
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: windowModeListModel
|
||||
@@ -348,16 +373,27 @@ ScrollView {
|
||||
onActivated: {
|
||||
prefs.windowMode = windowModeListModel.get(currentIndex).val
|
||||
}
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: "Full-screen generally provides the best performance, but borderless windowed may work better with features like macOS Spaces, Alt+Tab, screenshot tools, on-screen overlays, etc."
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: vsyncCheck
|
||||
hoverEnabled: true
|
||||
text: "<font color=\"white\">Enable V-Sync</font>"
|
||||
font.pointSize: 12
|
||||
checked: prefs.enableVsync
|
||||
onCheckedChanged: {
|
||||
prefs.enableVsync = checked
|
||||
}
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: "Disabling V-Sync allows sub-frame rendering latency, but it can display visible tearing"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,6 +455,29 @@ ScrollView {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
id: uiSettingsGroupBox
|
||||
width: (parent.width - 2 * parent.padding)
|
||||
padding: 12
|
||||
title: "<font color=\"skyblue\">UI Settings</font>"
|
||||
font.pointSize: 12
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
CheckBox {
|
||||
id: startWindowedCheck
|
||||
text: "<font color=\"white\">Start Moonlight in windowed mode</font>"
|
||||
font.pointSize: 12
|
||||
checked: prefs.startWindowed
|
||||
onCheckedChanged: {
|
||||
prefs.startWindowed = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -434,7 +493,7 @@ ScrollView {
|
||||
title: "<font color=\"skyblue\">Input Settings</font>"
|
||||
font.pointSize: 12
|
||||
|
||||
Row {
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
@@ -449,13 +508,19 @@ ScrollView {
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: mouseAccelerationCheck
|
||||
text: "<font color=\"white\">Enable mouse acceleration</font>"
|
||||
id: rawInputCheck
|
||||
hoverEnabled: true
|
||||
text: "<font color=\"white\">Raw mouse input</font>"
|
||||
font.pointSize: 12
|
||||
checked: prefs.mouseAcceleration
|
||||
checked: !prefs.mouseAcceleration
|
||||
onCheckedChanged: {
|
||||
prefs.mouseAcceleration = checked
|
||||
prefs.mouseAcceleration = !checked
|
||||
}
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 3000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: "When checked, mouse input is not accelerated or scaled by the OS before passing to Moonlight"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,15 +532,13 @@ ScrollView {
|
||||
title: "<font color=\"skyblue\">Host Settings</font>"
|
||||
font.pointSize: 12
|
||||
|
||||
Row {
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
CheckBox {
|
||||
id: optimizeGameSettingsCheck
|
||||
text: "<font color=\"white\">Optimize game settings</font>"
|
||||
// HACK: Match width of the other checkbox to make the UI not look bad
|
||||
width: multiControllerCheck.width
|
||||
font.pointSize: 12
|
||||
checked: prefs.gameOptimizations
|
||||
onCheckedChanged: {
|
||||
|
||||
+17
-1
@@ -3,6 +3,7 @@ import QtQuick.Controls 2.2
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
import SdlGamepadKeyNavigation 1.0
|
||||
import Session 1.0
|
||||
|
||||
Item {
|
||||
@@ -58,11 +59,26 @@ Item {
|
||||
toast.visible = true
|
||||
}
|
||||
|
||||
// It's important that we don't call enable() here
|
||||
// or it may interfere with the Session instance
|
||||
// getting notified of initial connected gamepads.
|
||||
SdlGamepadKeyNavigation {
|
||||
id: gamepadKeyNav
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
// Hide the toolbar before we start loading
|
||||
toolBar.visible = false
|
||||
|
||||
// Set the hint text. We do this here rather than
|
||||
// in the hintText control itself to synchronize
|
||||
// with Session.exec() which requires no concurrent
|
||||
// gamepad usage.
|
||||
hintText.text = gamepadKeyNav.getConnectedGamepads() > 0 ?
|
||||
"Tip: Press Start+Select+L1+R1 to disconnect your session" :
|
||||
"Tip: Press Ctrl+Alt+Shift+Q to disconnect your session"
|
||||
|
||||
// Hook up our signals
|
||||
session.stageStarting.connect(stageStarting)
|
||||
session.stageFailed.connect(stageFailed)
|
||||
@@ -118,7 +134,7 @@ Item {
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Tip: Press Ctrl+Alt+Shift+Q to disconnect your session"
|
||||
id: hintText
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 50
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
+78
-21
@@ -18,11 +18,7 @@ ApplicationWindow {
|
||||
width: 1280
|
||||
height: 600
|
||||
|
||||
// Maximize the window by default when the stream is configured
|
||||
// for full-screen or borderless windowed. This is ideal for TV
|
||||
// setups where the user doesn't want a tiny window in the middle
|
||||
// of their screen when starting Moonlight.
|
||||
visibility: prefs.windowMode != StreamingPreferences.WM_WINDOWED ? "Maximized" : "Windowed"
|
||||
visibility: prefs.startWindowed ? "Windowed" : "Maximized"
|
||||
|
||||
Material.theme: Material.Dark
|
||||
Material.accent: Material.Purple
|
||||
@@ -48,12 +44,18 @@ ApplicationWindow {
|
||||
if (depth > 1) {
|
||||
stackView.pop()
|
||||
}
|
||||
else {
|
||||
quitConfirmationDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onBackPressed: {
|
||||
if (depth > 1) {
|
||||
stackView.pop()
|
||||
}
|
||||
else {
|
||||
quitConfirmationDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onMenuPressed: {
|
||||
@@ -68,21 +70,59 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
onVisibilityChanged: {
|
||||
// We don't want to just use 'active' here because that will stop polling if
|
||||
// we lose focus, which might be overzealous for users with multiple screens
|
||||
// where we may be clearly visible on the other display. Ideally we'll poll
|
||||
// only if the window is visible to the user (not if obscured by other windows),
|
||||
// but it seems difficult to do this portably.
|
||||
var shouldPoll = visibility !== Window.Minimized && visibility !== Window.Hidden
|
||||
|
||||
if (shouldPoll && !pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
// This timer keeps us polling for 5 minutes of inactivity
|
||||
// to allow the user to work with Moonlight on a second display
|
||||
// while dealing with configuration issues. This will ensure
|
||||
// machines come online even if the input focus isn't on Moonlight.
|
||||
Timer {
|
||||
id: inactivityTimer
|
||||
interval: 5 * 60000
|
||||
onTriggered: {
|
||||
if (!active && pollingActive) {
|
||||
ComputerManager.stopPollingAsync()
|
||||
pollingActive = false
|
||||
}
|
||||
}
|
||||
else if (!shouldPoll && pollingActive) {
|
||||
ComputerManager.stopPollingAsync()
|
||||
pollingActive = false
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
// When we become invisible while streaming is going on,
|
||||
// stop polling immediately.
|
||||
if (!visible) {
|
||||
inactivityTimer.stop()
|
||||
|
||||
if (pollingActive) {
|
||||
ComputerManager.stopPollingAsync()
|
||||
pollingActive = false
|
||||
}
|
||||
}
|
||||
else if (active) {
|
||||
// When we become visible and active again, start polling
|
||||
inactivityTimer.stop()
|
||||
|
||||
// Restart polling if it was stopped
|
||||
if (!pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
if (active) {
|
||||
// Stop the inactivity timer
|
||||
inactivityTimer.stop()
|
||||
|
||||
// Restart polling if it was stopped
|
||||
if (!pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Start the inactivity timer to stop polling
|
||||
// if focus does not return within a few minutes.
|
||||
inactivityTimer.restart()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +137,11 @@ ApplicationWindow {
|
||||
// Doing it earlier can lead to the dialog appearing behind
|
||||
// the window or otherwise without input focus.
|
||||
if (!initialized) {
|
||||
// Set initialized before calling anything else, because
|
||||
// pumping the event loop can cause us to get another
|
||||
// onAfterRendering call and potentially reenter this code.
|
||||
initialized = true;
|
||||
|
||||
if (prefs.isRunningWayland()) {
|
||||
waylandDialog.open()
|
||||
}
|
||||
@@ -112,8 +157,6 @@ ApplicationWindow {
|
||||
unmappedGamepadDialog.unmappedGamepads = unmappedGamepads
|
||||
unmappedGamepadDialog.open()
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,4 +396,18 @@ ApplicationWindow {
|
||||
Qt.openUrlExternally("https://github.com/moonlight-stream/moonlight-docs/wiki/Gamepad-Mapping");
|
||||
}
|
||||
}
|
||||
|
||||
// This dialog appears when quitting via keyboard or gamepad button
|
||||
MessageDialog {
|
||||
id: quitConfirmationDialog
|
||||
modality:Qt.WindowModal
|
||||
icon: StandardIcon.Warning
|
||||
standardButtons: StandardButton.Yes | StandardButton.No
|
||||
text: "Are you sure you want to quit?"
|
||||
|
||||
onYes: Qt.quit()
|
||||
|
||||
// For keyboard/gamepad navigation
|
||||
onAccepted: Qt.quit()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,3 +244,23 @@ void SdlGamepadKeyNavigation::setSettingsMode(bool settingsMode)
|
||||
{
|
||||
m_SettingsMode = settingsMode;
|
||||
}
|
||||
|
||||
int SdlGamepadKeyNavigation::getConnectedGamepads()
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s",
|
||||
SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ public:
|
||||
|
||||
Q_INVOKABLE void setSettingsMode(bool settingsMode);
|
||||
|
||||
Q_INVOKABLE int getConnectedGamepads();
|
||||
|
||||
private:
|
||||
void sendKey(QEvent::Type type, Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
|
||||
|
||||
+19
-1
@@ -5,6 +5,7 @@
|
||||
#include <QQuickStyle>
|
||||
#include <QMutex>
|
||||
#include <QtDebug>
|
||||
#include <QNetworkProxyFactory>
|
||||
|
||||
// Don't let SDL hook our main function, since Qt is already
|
||||
// doing the same thing. This needs to be before any headers
|
||||
@@ -16,6 +17,10 @@
|
||||
#include "streaming/video/ffmpeg.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#include "antihookingprotection.h"
|
||||
#endif
|
||||
|
||||
#include "cli/startstream.h"
|
||||
#include "cli/commandlineparser.h"
|
||||
#include "path.h"
|
||||
@@ -263,6 +268,12 @@ int main(int argc, char *argv[])
|
||||
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
// Force AntiHooking.dll to be statically imported and loaded
|
||||
// by ntdll by calling a dummy function.
|
||||
AntiHookingDummyImport();
|
||||
#endif
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
|
||||
// This avoids using the default keychain for SSL, which may cause
|
||||
@@ -278,6 +289,13 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
// We don't want system proxies to apply to us
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(false);
|
||||
|
||||
// Clear any default application proxy
|
||||
QNetworkProxy noProxy(QNetworkProxy::NoProxy);
|
||||
QNetworkProxy::setApplicationProxy(noProxy);
|
||||
|
||||
// Register custom metatypes for use in signals
|
||||
qRegisterMetaType<NvApp>("NvApp");
|
||||
|
||||
@@ -334,7 +352,7 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
|
||||
SDL_SetMainReady();
|
||||
if (SDL_Init(0) != 0) {
|
||||
if (SDL_Init(SDL_INIT_TIMER) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_Init() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define SER_UNSUPPORTEDFPS "unsupportedfps"
|
||||
#define SER_MDNS "mdns"
|
||||
#define SER_MOUSEACCELERATION "mouseacceleration"
|
||||
#define SER_STARTWINDOWED "startwindowed"
|
||||
|
||||
StreamingPreferences::StreamingPreferences(QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -43,6 +44,7 @@ void StreamingPreferences::reload()
|
||||
unsupportedFps = settings.value(SER_UNSUPPORTEDFPS, false).toBool();
|
||||
enableMdns = settings.value(SER_MDNS, true).toBool();
|
||||
mouseAcceleration = settings.value(SER_MOUSEACCELERATION, false).toBool();
|
||||
startWindowed = settings.value(SER_STARTWINDOWED, false).toBool();
|
||||
audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG,
|
||||
static_cast<int>(AudioConfig::AC_STEREO)).toInt());
|
||||
videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG,
|
||||
@@ -70,6 +72,7 @@ void StreamingPreferences::save()
|
||||
settings.setValue(SER_UNSUPPORTEDFPS, unsupportedFps);
|
||||
settings.setValue(SER_MDNS, enableMdns);
|
||||
settings.setValue(SER_MOUSEACCELERATION, mouseAcceleration);
|
||||
settings.setValue(SER_STARTWINDOWED, startWindowed);
|
||||
settings.setValue(SER_AUDIOCFG, static_cast<int>(audioConfig));
|
||||
settings.setValue(SER_VIDEOCFG, static_cast<int>(videoCodecConfig));
|
||||
settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection));
|
||||
@@ -133,9 +136,7 @@ int StreamingPreferences::getMaximumStreamingFrameRate()
|
||||
}
|
||||
}
|
||||
|
||||
// Cap the frame rate at 120 FPS. Past this, the encoders start
|
||||
// to max out and drop frames.
|
||||
maxFrameRate = qMax(maxFrameRate, qMin(120, bestMode.refresh_rate));
|
||||
maxFrameRate = qMax(maxFrameRate, bestMode.refresh_rate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
Q_PROPERTY(bool unsupportedFps MEMBER unsupportedFps NOTIFY unsupportedFpsChanged)
|
||||
Q_PROPERTY(bool enableMdns MEMBER enableMdns NOTIFY enableMdnsChanged)
|
||||
Q_PROPERTY(bool mouseAcceleration MEMBER mouseAcceleration NOTIFY mouseAccelerationChanged)
|
||||
Q_PROPERTY(bool startWindowed MEMBER startWindowed NOTIFY startWindowedChanged)
|
||||
Q_PROPERTY(AudioConfig audioConfig MEMBER audioConfig NOTIFY audioConfigChanged)
|
||||
Q_PROPERTY(VideoCodecConfig videoCodecConfig MEMBER videoCodecConfig NOTIFY videoCodecConfigChanged)
|
||||
Q_PROPERTY(VideoDecoderSelection videoDecoderSelection MEMBER videoDecoderSelection NOTIFY videoDecoderSelectionChanged)
|
||||
@@ -91,6 +92,7 @@ public:
|
||||
bool unsupportedFps;
|
||||
bool enableMdns;
|
||||
bool mouseAcceleration;
|
||||
bool startWindowed;
|
||||
AudioConfig audioConfig;
|
||||
VideoCodecConfig videoCodecConfig;
|
||||
VideoDecoderSelection videoDecoderSelection;
|
||||
@@ -110,5 +112,6 @@ signals:
|
||||
void videoCodecConfigChanged();
|
||||
void videoDecoderSelectionChanged();
|
||||
void windowModeChanged();
|
||||
void startWindowedChanged();
|
||||
};
|
||||
|
||||
|
||||
+73
-70
@@ -17,6 +17,8 @@
|
||||
#define VK_NUMPAD0 0x60
|
||||
#endif
|
||||
|
||||
#define MOUSE_POLLING_INTERVAL 5
|
||||
|
||||
// How long the mouse button will be pressed for a tap to click gesture
|
||||
#define TAP_BUTTON_RELEASE_DELAY 100
|
||||
|
||||
@@ -34,10 +36,9 @@ const int SdlInputHandler::k_ButtonMap[] = {
|
||||
UP_FLAG, DOWN_FLAG, LEFT_FLAG, RIGHT_FLAG
|
||||
};
|
||||
|
||||
SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer* computer, int streamWidth, int streamHeight)
|
||||
: m_LastMouseMotionTime(0),
|
||||
m_MultiController(prefs.multiController),
|
||||
m_NeedsInputDelay(false),
|
||||
SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int streamWidth, int streamHeight)
|
||||
: m_MultiController(prefs.multiController),
|
||||
m_MouseMoveTimer(0),
|
||||
m_LeftButtonReleaseTimer(0),
|
||||
m_RightButtonReleaseTimer(0),
|
||||
m_DragTimer(0),
|
||||
@@ -68,31 +69,19 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer* comput
|
||||
MappingManager mappingManager;
|
||||
mappingManager.applyMappings();
|
||||
|
||||
if (!m_MultiController) {
|
||||
// Player 1 is always present in non-MC mode
|
||||
m_GamepadMask = 0x1;
|
||||
}
|
||||
else {
|
||||
// Otherwise, detect gamepads on the fly
|
||||
m_GamepadMask = 0;
|
||||
}
|
||||
|
||||
// Prior to GFE 3.14.1, sending too many mouse motion events can cause
|
||||
// GFE to choke and input latency to increase significantly. We will
|
||||
// artificially throttle them to avoid this situation.
|
||||
QVector<int> gfeVersion = NvHTTP::parseQuad(computer->gfeVersion);
|
||||
if (gfeVersion.isEmpty() || // Very old versions don't have GfeVersion at all
|
||||
gfeVersion[0] < 3 ||
|
||||
(gfeVersion[0] == 3 && gfeVersion[1] < 14) ||
|
||||
(gfeVersion[0] == 3 && gfeVersion[1] == 14 && gfeVersion[2] < 1)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"This older version of GFE requires input delay hack");
|
||||
m_NeedsInputDelay = true;
|
||||
}
|
||||
// Initialize the gamepad mask with currently attached gamepads to avoid
|
||||
// causing gamepads to unexpectedly disappear and reappear on the host
|
||||
// during stream startup as we detect currently attached gamepads one at a time.
|
||||
m_GamepadMask = getAttachedGamepadMask();
|
||||
|
||||
SDL_zero(m_GamepadState);
|
||||
SDL_zero(m_TouchDownEvent);
|
||||
SDL_zero(m_CumulativeDelta);
|
||||
|
||||
SDL_AtomicSet(&m_MouseDeltaX, 0);
|
||||
SDL_AtomicSet(&m_MouseDeltaY, 0);
|
||||
|
||||
m_MouseMoveTimer = SDL_AddTimer(MOUSE_POLLING_INTERVAL, SdlInputHandler::mouseMoveTimerCallback, this);
|
||||
}
|
||||
|
||||
SdlInputHandler::~SdlInputHandler()
|
||||
@@ -103,6 +92,7 @@ SdlInputHandler::~SdlInputHandler()
|
||||
}
|
||||
}
|
||||
|
||||
SDL_RemoveTimer(m_MouseMoveTimer);
|
||||
SDL_RemoveTimer(m_LeftButtonReleaseTimer);
|
||||
SDL_RemoveTimer(m_RightButtonReleaseTimer);
|
||||
SDL_RemoveTimer(m_DragTimer);
|
||||
@@ -459,40 +449,10 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
|
||||
return;
|
||||
}
|
||||
|
||||
short xdelta = (short)event->xrel;
|
||||
short ydelta = (short)event->yrel;
|
||||
|
||||
// If we're sending more than one motion event per millisecond,
|
||||
// delay for 1 ms to allow batching of mouse move events. On older
|
||||
// versions of GFE, we will unconditionally wait this 1 ms to
|
||||
// work around an input processing issue that causes massive mouse latency.
|
||||
Uint32 currentTime = SDL_GetTicks();
|
||||
if (m_NeedsInputDelay || !SDL_TICKS_PASSED(currentTime, m_LastMouseMotionTime + 1)) {
|
||||
SDL_Delay(1);
|
||||
currentTime = SDL_GetTicks();
|
||||
}
|
||||
m_LastMouseMotionTime = currentTime;
|
||||
|
||||
// Pump even if we didn't delay since we might get some extra events
|
||||
SDL_PumpEvents();
|
||||
|
||||
// Batch all of the pending mouse motion events
|
||||
SDL_Event nextEvent;
|
||||
while (SDL_PeepEvents(&nextEvent,
|
||||
1,
|
||||
SDL_GETEVENT,
|
||||
SDL_MOUSEMOTION,
|
||||
SDL_MOUSEMOTION) == 1) {
|
||||
// In theory, these can overflow but in practice
|
||||
// it should be highly unlikely since it would require
|
||||
// moving 64K pixels in 1 ms.
|
||||
xdelta += nextEvent.motion.xrel;
|
||||
ydelta += nextEvent.motion.yrel;
|
||||
}
|
||||
|
||||
if (xdelta != 0 || ydelta != 0) {
|
||||
LiSendMouseMoveEvent(xdelta, ydelta);
|
||||
}
|
||||
// Batch until the next mouse polling window or we'll get awful
|
||||
// input lag everything except GFE 3.14 and 3.15.
|
||||
SDL_AtomicAdd(&m_MouseDeltaX, event->xrel);
|
||||
SDL_AtomicAdd(&m_MouseDeltaY, event->yrel);
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event)
|
||||
@@ -572,6 +532,20 @@ Uint32 SdlInputHandler::dragTimerCallback(Uint32, void *param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uint32 SdlInputHandler::mouseMoveTimerCallback(Uint32 interval, void *param)
|
||||
{
|
||||
auto me = reinterpret_cast<SdlInputHandler*>(param);
|
||||
|
||||
short deltaX = (short)SDL_AtomicSet(&me->m_MouseDeltaX, 0);
|
||||
short deltaY = (short)SDL_AtomicSet(&me->m_MouseDeltaY, 0);
|
||||
|
||||
if (deltaX != 0 || deltaY != 0) {
|
||||
LiSendMouseMoveEvent(deltaX, deltaY);
|
||||
}
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
{
|
||||
GamepadState* state = findStateForGamepad(event->which);
|
||||
@@ -655,8 +629,31 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||
int i;
|
||||
const char* name;
|
||||
SDL_GameController* controller;
|
||||
const char* mapping;
|
||||
char guidStr[33];
|
||||
|
||||
for (i = 0; i < MAX_GAMEPADS; i++) {
|
||||
controller = SDL_GameControllerOpen(event->which);
|
||||
if (controller == NULL) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to open gamepad: %s",
|
||||
SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
||||
// Determine this player's preferred index
|
||||
i = SDL_GameControllerGetPlayerIndex(controller);
|
||||
if (i < 0 || i >= MAX_GAMEPADS || m_GamepadState[i].controller != NULL) {
|
||||
// If the player index is unavailable or invalid, start searching from 0
|
||||
i = 0;
|
||||
}
|
||||
#else
|
||||
// SDL 2.0.8 and earlier has no player number hints
|
||||
i = 0;
|
||||
#endif
|
||||
|
||||
for (; i < MAX_GAMEPADS; i++) {
|
||||
if (m_GamepadState[i].controller == NULL) {
|
||||
// Found an empty slot
|
||||
break;
|
||||
@@ -666,6 +663,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
if (i == MAX_GAMEPADS) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No open gamepad slots found!");
|
||||
SDL_GameControllerClose(controller);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -677,26 +675,30 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
// Always player 1 in single controller mode
|
||||
state->index = 0;
|
||||
}
|
||||
state->controller = SDL_GameControllerOpen(event->which);
|
||||
if (state->controller == NULL) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to open gamepad: %s",
|
||||
SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
state->controller = controller;
|
||||
state->jsId = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(state->controller));
|
||||
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(SDL_GameControllerGetJoystick(state->controller)),
|
||||
guidStr, sizeof(guidStr));
|
||||
mapping = SDL_GameControllerMapping(state->controller);
|
||||
name = SDL_GameControllerName(state->controller);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Gamepad %d (player %d) is: %s",
|
||||
"Gamepad %d (player %d) is: %s (%s -> %s)",
|
||||
i,
|
||||
state->index,
|
||||
name != NULL ? name : "<null>");
|
||||
name != nullptr ? name : "<null>",
|
||||
guidStr,
|
||||
mapping != nullptr ? mapping : "<null>");
|
||||
if (mapping != nullptr) {
|
||||
SDL_free((void*)mapping);
|
||||
}
|
||||
|
||||
// Add this gamepad to the gamepad mask
|
||||
if (m_MultiController) {
|
||||
SDL_assert(!(m_GamepadMask & (1 << state->index)));
|
||||
// NB: Don't assert that it's unset here because we will already
|
||||
// have the mask set for initially attached gamepads to avoid confusing
|
||||
// apps running on the host.
|
||||
m_GamepadMask |= (1 << state->index);
|
||||
}
|
||||
else {
|
||||
@@ -908,6 +910,7 @@ int SdlInputHandler::getAttachedGamepadMask()
|
||||
return 0x1;
|
||||
}
|
||||
|
||||
// TODO: Use SDL_GameControllerGetPlayerIndex() for accurate indexes?
|
||||
count = mask = 0;
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
|
||||
@@ -67,9 +67,13 @@ private:
|
||||
static
|
||||
Uint32 dragTimerCallback(Uint32 interval, void* param);
|
||||
|
||||
Uint32 m_LastMouseMotionTime;
|
||||
static
|
||||
Uint32 mouseMoveTimerCallback(Uint32 interval, void* param);
|
||||
|
||||
bool m_MultiController;
|
||||
bool m_NeedsInputDelay;
|
||||
SDL_TimerID m_MouseMoveTimer;
|
||||
SDL_atomic_t m_MouseDeltaX;
|
||||
SDL_atomic_t m_MouseDeltaY;
|
||||
int m_GamepadMask;
|
||||
GamepadState m_GamepadState[MAX_GAMEPADS];
|
||||
QSet<short> m_KeysDown;
|
||||
|
||||
+67
-67
@@ -6,12 +6,6 @@
|
||||
#include <SDL.h>
|
||||
#include "utils.h"
|
||||
|
||||
// HACK: Need to call SetThreadExecutionState() because SDL doesn't
|
||||
#ifdef Q_OS_WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include "video/ffmpeg.h"
|
||||
#endif
|
||||
@@ -228,11 +222,14 @@ bool Session::isHardwareDecodeAvailable(StreamingPreferences::VideoDecoderSelect
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
bool ret = decoder->isHardwareAccelerated();
|
||||
|
||||
delete decoder;
|
||||
|
||||
// This must be called after the decoder is deleted, because
|
||||
// the renderer may want to interact with the window
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
return ret;
|
||||
@@ -265,11 +262,14 @@ int Session::getDecoderCapabilities(StreamingPreferences::VideoDecoderSelection
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
int caps = decoder->getDecoderCapabilities();
|
||||
|
||||
delete decoder;
|
||||
|
||||
// This must be called after the decoder is deleted, because
|
||||
// the renderer may want to interact with the window
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
return caps;
|
||||
@@ -350,6 +350,22 @@ void Session::initialize()
|
||||
m_StreamConfig.width,
|
||||
m_StreamConfig.height,
|
||||
m_StreamConfig.fps);
|
||||
#ifdef Q_OS_DARWIN
|
||||
{
|
||||
// Prior to GFE 3.11, GFE did not allow us to constrain
|
||||
// the number of reference frames, so we have to fixup the SPS
|
||||
// to allow decoding via VideoToolbox on macOS. Since we don't
|
||||
// have fixup code for HEVC, just avoid it if GFE is too old.
|
||||
QVector<int> gfeVersion = NvHTTP::parseQuad(m_Computer->gfeVersion);
|
||||
if (gfeVersion.isEmpty() || // Very old versions don't have GfeVersion at all
|
||||
gfeVersion[0] < 3 ||
|
||||
(gfeVersion[0] == 3 && gfeVersion[1] < 11)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Disabling HEVC on macOS due to old GFE version");
|
||||
m_StreamConfig.supportsHevc = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_StreamConfig.enableHdr = false;
|
||||
break;
|
||||
case StreamingPreferences::VCC_FORCE_H264:
|
||||
@@ -489,15 +505,6 @@ bool Session::validateLaunch()
|
||||
if (m_Computer->gfeVersion.isEmpty() || m_Computer->gfeVersion.startsWith("2.")) {
|
||||
emitLaunchWarning("GeForce Experience 3.0 or higher is required for 4K streaming.");
|
||||
|
||||
m_StreamConfig.width = 1920;
|
||||
m_StreamConfig.height = 1080;
|
||||
}
|
||||
// This list is sorted from least to greatest
|
||||
else if (m_Computer->displayModes.last().width < 3840 ||
|
||||
(m_Computer->displayModes.last().refreshRate < 60 && m_StreamConfig.fps >= 60)) {
|
||||
emitLaunchWarning("Your host PC GPU doesn't support 4K streaming. "
|
||||
"A GeForce GTX 900-series (Maxwell) or later GPU is required for 4K streaming.");
|
||||
|
||||
m_StreamConfig.width = 1920;
|
||||
m_StreamConfig.height = 1080;
|
||||
}
|
||||
@@ -571,10 +578,12 @@ void Session::getWindowDimensions(int& x, int& y,
|
||||
int& width, int& height)
|
||||
{
|
||||
int displayIndex = 0;
|
||||
bool fullScreen;
|
||||
|
||||
if (m_Window != nullptr) {
|
||||
displayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
SDL_assert(displayIndex >= 0);
|
||||
fullScreen = (SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN);
|
||||
}
|
||||
// Create our window on the same display that Qt's UI
|
||||
// was being displayed on.
|
||||
@@ -601,10 +610,16 @@ void Session::getWindowDimensions(int& x, int& y,
|
||||
i, SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
fullScreen = (m_Preferences->windowMode != StreamingPreferences::WM_WINDOWED);
|
||||
}
|
||||
|
||||
SDL_Rect usableBounds;
|
||||
if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
|
||||
if (fullScreen && SDL_GetDisplayBounds(displayIndex, &usableBounds) == 0) {
|
||||
width = usableBounds.w;
|
||||
height = usableBounds.h;
|
||||
}
|
||||
else if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
|
||||
width = usableBounds.w;
|
||||
height = usableBounds.h;
|
||||
|
||||
@@ -689,9 +704,13 @@ void Session::updateOptimalWindowDisplayMode()
|
||||
bestMode = desktopMode;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Chosen best display mode: %dx%dx%d",
|
||||
bestMode.w, bestMode.h, bestMode.refresh_rate);
|
||||
if ((SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
|
||||
// Only print when the window is actually in full-screen exclusive mode,
|
||||
// otherwise we're not actually using the mode we've set here
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Chosen best display mode: %dx%dx%d",
|
||||
bestMode.w, bestMode.h, bestMode.refresh_rate);
|
||||
}
|
||||
|
||||
SDL_SetWindowDisplayMode(m_Window, &bestMode);
|
||||
}
|
||||
@@ -755,18 +774,6 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||
Q_ASSERT(m_Computer->currentGameId == 0 ||
|
||||
m_Computer->currentGameId == m_App.id);
|
||||
|
||||
bool enableGameOptimizations = false;
|
||||
for (const NvDisplayMode &mode : m_Computer->displayModes) {
|
||||
if (mode.width == m_StreamConfig.width &&
|
||||
mode.height == m_StreamConfig.height) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Found host supported resolution: %dx%d",
|
||||
mode.width, mode.height);
|
||||
enableGameOptimizations = prefs.gameOptimizations;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
NvHTTP http(m_Computer->activeAddress);
|
||||
if (m_Computer->currentGameId != 0) {
|
||||
@@ -774,7 +781,7 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||
}
|
||||
else {
|
||||
http.launchApp(m_App.id, &m_StreamConfig,
|
||||
enableGameOptimizations,
|
||||
prefs.gameOptimizations,
|
||||
prefs.playAudioOnHost,
|
||||
inputHandler.getAttachedGamepadMask());
|
||||
}
|
||||
@@ -848,6 +855,27 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||
return;
|
||||
}
|
||||
|
||||
QSvgRenderer svgIconRenderer(QString(":/res/moonlight.svg"));
|
||||
QImage svgImage(ICON_SIZE, ICON_SIZE, QImage::Format_RGBA8888);
|
||||
svgImage.fill(0);
|
||||
|
||||
QPainter svgPainter(&svgImage);
|
||||
svgIconRenderer.render(&svgPainter);
|
||||
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)svgImage.constBits(),
|
||||
svgImage.width(),
|
||||
svgImage.height(),
|
||||
32,
|
||||
4 * svgImage.width(),
|
||||
SDL_PIXELFORMAT_RGBA32);
|
||||
#ifndef Q_OS_DARWIN
|
||||
// Other platforms seem to preserve our Qt icon when creating a new window.
|
||||
if (iconSurface != nullptr) {
|
||||
// This must be called before entering full-screen mode on Windows
|
||||
// or our icon will not persist when toggling to windowed mode
|
||||
SDL_SetWindowIcon(m_Window, iconSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
// For non-full screen windows, call getWindowDimensions()
|
||||
// again after creating a window to allow it to account
|
||||
// for window chrome size.
|
||||
@@ -871,25 +899,6 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||
SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag);
|
||||
}
|
||||
|
||||
QSvgRenderer svgIconRenderer(QString(":/res/moonlight.svg"));
|
||||
QImage svgImage(ICON_SIZE, ICON_SIZE, QImage::Format_RGBA8888);
|
||||
svgImage.fill(0);
|
||||
|
||||
QPainter svgPainter(&svgImage);
|
||||
svgIconRenderer.render(&svgPainter);
|
||||
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)svgImage.constBits(),
|
||||
svgImage.width(),
|
||||
svgImage.height(),
|
||||
32,
|
||||
4 * svgImage.width(),
|
||||
SDL_PIXELFORMAT_RGBA32);
|
||||
#ifndef Q_OS_DARWIN
|
||||
// Other platforms seem to preserve our Qt icon when creating a new window
|
||||
if (iconSurface != nullptr) {
|
||||
SDL_SetWindowIcon(m_Window, iconSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef QT_DEBUG
|
||||
// Capture the mouse by default on release builds only.
|
||||
// This prevents the mouse from becoming trapped inside
|
||||
@@ -908,13 +917,6 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||
// Disable the screen saver
|
||||
SDL_DisableScreenSaver();
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
// HACK: SDL doesn't call this, so we must do so to disable the
|
||||
// screensaver when we're in windowed mode. DirectX will disable
|
||||
// it for us when we're in full-screen exclusive mode.
|
||||
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
|
||||
#endif
|
||||
|
||||
// Set timer resolution to 1 ms on Windows for greater
|
||||
// sleep precision and more accurate callback timing.
|
||||
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1");
|
||||
@@ -1134,11 +1136,6 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
||||
}
|
||||
|
||||
DispatchDeferredCleanup:
|
||||
#ifdef Q_OS_WIN32
|
||||
// HACK: See comment above
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
#endif
|
||||
|
||||
// Uncapture the mouse and hide the window immediately,
|
||||
// so we can return to the Qt GUI ASAP.
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
@@ -1154,7 +1151,10 @@ DispatchDeferredCleanup:
|
||||
m_VideoDecoder = nullptr;
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
|
||||
// This must be called after the decoder is deleted, because
|
||||
// the renderer may want to interact with the window
|
||||
SDL_DestroyWindow(m_Window);
|
||||
|
||||
if (iconSurface != nullptr) {
|
||||
SDL_FreeSurface(iconSurface);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <QString>
|
||||
|
||||
#include "vaapi.h"
|
||||
#include <streaming/streamutils.h>
|
||||
|
||||
@@ -114,6 +116,21 @@ VAAPIRenderer::initialize(SDL_Window* window, int, int width, int height, int, b
|
||||
"Driver: %s",
|
||||
vendorString ? vendorString : "<unknown>");
|
||||
|
||||
// AMD's Gallium VAAPI driver has a nasty memory leak
|
||||
// that causes memory to be leaked for each submitted frame.
|
||||
// The Flatpak runtime has a VDPAU driver in place that works
|
||||
// well, so use that instead on AMD systems.
|
||||
if (vendorString && qgetenv("FORCE_VAAPI") != "1") {
|
||||
QString vendorStr(vendorString);
|
||||
if (vendorStr.contains("AMD", Qt::CaseInsensitive) ||
|
||||
vendorStr.contains("Radeon", Qt::CaseInsensitive)) {
|
||||
// Fail and let VDPAU pick this up
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Avoiding VAAPI on AMD driver");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This will populate the driver_quirks
|
||||
err = av_hwdevice_ctx_init(m_HwContext);
|
||||
if (err < 0) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <Limelight.h>
|
||||
#include "ffmpeg.h"
|
||||
#include "streaming/streamutils.h"
|
||||
#include <h264_stream.h>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#include "ffmpeg-renderers/dxva2.h"
|
||||
@@ -21,6 +22,8 @@
|
||||
// This is gross but it allows us to use sizeof()
|
||||
#include "ffmpeg_videosamples.cpp"
|
||||
|
||||
#define MAX_SPS_EXTRA_SIZE 16
|
||||
|
||||
#define FAILED_DECODES_RESET_THRESHOLD 20
|
||||
|
||||
bool FFmpegVideoDecoder::isHardwareAccelerated()
|
||||
@@ -62,7 +65,8 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
|
||||
m_ConsecutiveFailedDecodes(0),
|
||||
m_Pacer(nullptr),
|
||||
m_LastFrameNumber(0),
|
||||
m_StreamFps(0)
|
||||
m_StreamFps(0),
|
||||
m_NeedsSpsFixup(false)
|
||||
{
|
||||
av_init_packet(&m_Pkt);
|
||||
SDL_AtomicSet(&m_QueuedFrames, 0);
|
||||
@@ -225,6 +229,17 @@ bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, SDL_Window* wi
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((videoFormat & VIDEO_FORMAT_MASK_H264) &&
|
||||
!(m_Renderer->getDecoderCapabilities() & CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC)) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Using H.264 SPS fixup");
|
||||
m_NeedsSpsFixup = true;
|
||||
}
|
||||
else {
|
||||
m_NeedsSpsFixup = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
// Restore default log level before streaming
|
||||
@@ -424,6 +439,49 @@ bool FFmpegVideoDecoder::initialize(
|
||||
}
|
||||
}
|
||||
|
||||
void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)
|
||||
{
|
||||
if (m_NeedsSpsFixup && entry->bufferType == BUFFER_TYPE_SPS) {
|
||||
const char naluHeader[] = {0x00, 0x00, 0x00, 0x01};
|
||||
h264_stream_t* stream = h264_new();
|
||||
int nalStart, nalEnd;
|
||||
|
||||
// Read the old NALU
|
||||
find_nal_unit((uint8_t*)entry->data, entry->length, &nalStart, &nalEnd);
|
||||
read_nal_unit(stream,
|
||||
(unsigned char *)&entry->data[nalStart],
|
||||
nalEnd - nalStart);
|
||||
|
||||
SDL_assert(nalStart == sizeof(naluHeader));
|
||||
SDL_assert(nalEnd == entry->length);
|
||||
|
||||
// Fixup the SPS to what OS X needs to use hardware acceleration
|
||||
stream->sps->num_ref_frames = 1;
|
||||
stream->sps->vui.max_dec_frame_buffering = 1;
|
||||
|
||||
int initialOffset = offset;
|
||||
|
||||
// Copy the modified NALU data. This assumes a 3 byte prefix and
|
||||
// begins writing from the 2nd byte, so we must write the data
|
||||
// first, then go back and write the Annex B prefix.
|
||||
offset += write_nal_unit(stream, (uint8_t*)&m_DecodeBuffer.data()[initialOffset + 3],
|
||||
MAX_SPS_EXTRA_SIZE + entry->length - sizeof(naluHeader));
|
||||
|
||||
// Copy the NALU prefix over from the original SPS
|
||||
memcpy(&m_DecodeBuffer.data()[initialOffset], naluHeader, sizeof(naluHeader));
|
||||
offset += sizeof(naluHeader);
|
||||
|
||||
h264_free(stream);
|
||||
}
|
||||
else {
|
||||
// Write the buffer as-is
|
||||
memcpy(&m_DecodeBuffer.data()[offset],
|
||||
entry->data,
|
||||
entry->length);
|
||||
offset += entry->length;
|
||||
}
|
||||
}
|
||||
|
||||
int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
{
|
||||
PLENTRY entry = du->bufferList;
|
||||
@@ -461,23 +519,23 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
m_LastFrameNumber = du->frameNumber;
|
||||
}
|
||||
|
||||
if (du->fullLength + AV_INPUT_BUFFER_PADDING_SIZE > m_DecodeBuffer.length()) {
|
||||
m_DecodeBuffer = QByteArray(du->fullLength + AV_INPUT_BUFFER_PADDING_SIZE, 0);
|
||||
int requiredBufferSize = du->fullLength;
|
||||
if (du->frameType == FRAME_TYPE_IDR) {
|
||||
// Add some extra space in case we need to do an SPS fixup
|
||||
requiredBufferSize += MAX_SPS_EXTRA_SIZE;
|
||||
}
|
||||
if (requiredBufferSize + AV_INPUT_BUFFER_PADDING_SIZE > m_DecodeBuffer.length()) {
|
||||
m_DecodeBuffer = QByteArray(requiredBufferSize + AV_INPUT_BUFFER_PADDING_SIZE, 0);
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
while (entry != nullptr) {
|
||||
memcpy(&m_DecodeBuffer.data()[offset],
|
||||
entry->data,
|
||||
entry->length);
|
||||
offset += entry->length;
|
||||
writeBuffer(entry, offset);
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
SDL_assert(offset == du->fullLength);
|
||||
|
||||
m_Pkt.data = reinterpret_cast<uint8_t*>(m_DecodeBuffer.data());
|
||||
m_Pkt.size = du->fullLength;
|
||||
m_Pkt.size = offset;
|
||||
|
||||
m_ActiveWndVideoStats.totalReassemblyTime += LiGetMillis() - du->receiveTimeMs;
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ private:
|
||||
|
||||
void reset();
|
||||
|
||||
void writeBuffer(PLENTRY entry, int& offset);
|
||||
|
||||
static
|
||||
enum AVPixelFormat ffGetFormat(AVCodecContext* context,
|
||||
const enum AVPixelFormat* pixFmts);
|
||||
@@ -57,6 +59,7 @@ private:
|
||||
VIDEO_STATS m_GlobalVideoStats;
|
||||
int m_LastFrameNumber;
|
||||
int m_StreamFps;
|
||||
bool m_NeedsSpsFixup;
|
||||
|
||||
static const uint8_t k_H264TestFrame[];
|
||||
static const uint8_t k_HEVCTestFrame[];
|
||||
|
||||
Submodule
+1
Submodule h264bitstream/h264bitstream added at 34f3c58afa
@@ -0,0 +1,46 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-10-12T15:50:59
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
|
||||
QT -= core gui
|
||||
|
||||
TARGET = h264bitstream
|
||||
TEMPLATE = lib
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
# Ensure symbols are always generated
|
||||
CONFIG += force_debug_info
|
||||
|
||||
# Build a static library
|
||||
CONFIG += staticlib
|
||||
|
||||
# Disable warnings
|
||||
CONFIG += warn_off
|
||||
|
||||
# Older GCC versions defaulted to GNU89
|
||||
*-g++ {
|
||||
QMAKE_CFLAGS += -std=gnu99
|
||||
}
|
||||
|
||||
SRC_DIR = $$PWD/h264bitstream
|
||||
|
||||
SOURCES += \
|
||||
$$SRC_DIR/h264_avcc.c \
|
||||
$$SRC_DIR/h264_nal.c \
|
||||
$$SRC_DIR/h264_sei.c \
|
||||
$$SRC_DIR/h264_slice_data.c \
|
||||
$$SRC_DIR/h264_stream.c
|
||||
|
||||
HEADERS += \
|
||||
$$SRC_DIR/bs.h \
|
||||
$$SRC_DIR/h264_avcc.h \
|
||||
$$SRC_DIR/h264_sei.h \
|
||||
$$SRC_DIR/h264_slice_data.h \
|
||||
$$SRC_DIR/h264_stream.h
|
||||
|
||||
INCLUDEPATH += $$INC_DIR
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Nektra S.A., Buenos Aires, Argentina.
|
||||
* All rights reserved. Contact: http://www.nektra.com
|
||||
*
|
||||
*
|
||||
* This file is part of Deviare In-Proc
|
||||
*
|
||||
*
|
||||
* Commercial License Usage
|
||||
* ------------------------
|
||||
* Licensees holding valid commercial Deviare In-Proc licenses may use this
|
||||
* file in accordance with the commercial license agreement provided with the
|
||||
* Software or, alternatively, in accordance with the terms contained in
|
||||
* a written agreement between you and Nektra. For licensing terms and
|
||||
* conditions see http://www.nektra.com/licensing/. For further information
|
||||
* use the contact form at http://www.nektra.com/contact/.
|
||||
*
|
||||
*
|
||||
* GNU General Public License Usage
|
||||
* --------------------------------
|
||||
* Alternatively, this file may be used under the terms of the GNU
|
||||
* General Public License version 3.0 as published by the Free Software
|
||||
* Foundation and appearing in the file LICENSE.GPL included in the
|
||||
* packaging of this file. Please review the following information to
|
||||
* ensure the GNU General Public License version 3.0 requirements will be
|
||||
* met: http://www.gnu.org/copyleft/gpl.html.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef _NKTHOOKLIB
|
||||
#define _NKTHOOKLIB
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
||||
#define NKTHOOKLIB_DontSkipInitialJumps 0x0001
|
||||
#define NKTHOOKLIB_DontRemoveOnUnhook 0x0002
|
||||
#define NKTHOOKLIB_DontSkipAnyJumps 0x0004
|
||||
#define NKTHOOKLIB_SkipNullProcsToHook 0x0008
|
||||
#define NKTHOOKLIB_UseAbsoluteIndirectJumps 0x0010
|
||||
#define NKTHOOKLIB_DisallowReentrancy 0x0020
|
||||
#define NKTHOOKLIB_DontEnableHooks 0x0040
|
||||
|
||||
#define NKTHOOKLIB_ProcessPlatformX86 1
|
||||
#define NKTHOOKLIB_ProcessPlatformX64 2
|
||||
|
||||
#define NKTHOOKLIB_CurrentProcess ((HANDLE)(LONG_PTR)-1)
|
||||
#define NKTHOOKLIB_CurrentThread ((HANDLE)(LONG_PTR)-2)
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
||||
class CNktHookLib
|
||||
{
|
||||
public:
|
||||
typedef struct tagHOOK_INFO {
|
||||
SIZE_T nHookId;
|
||||
LPVOID lpProcToHook;
|
||||
LPVOID lpNewProcAddr;
|
||||
//----
|
||||
LPVOID lpCallOriginal;
|
||||
} HOOK_INFO, *LPHOOK_INFO;
|
||||
|
||||
CNktHookLib();
|
||||
~CNktHookLib();
|
||||
|
||||
DWORD Hook(__out SIZE_T *lpnHookId, __out LPVOID *lplpCallOriginal, __in LPVOID lpProcToHook,
|
||||
__in LPVOID lpNewProcAddr, __in DWORD dwFlags=0);
|
||||
DWORD Hook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwFlags=0);
|
||||
DWORD Hook(__inout LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwFlags = 0);
|
||||
|
||||
DWORD RemoteHook(__out SIZE_T *lpnHookId, __out LPVOID *lplpCallOriginal, __in DWORD dwPid,
|
||||
__in LPVOID lpProcToHook, __in LPVOID lpNewProcAddr, __in DWORD dwFlags);
|
||||
DWORD RemoteHook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags);
|
||||
DWORD RemoteHook(__inout LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags);
|
||||
|
||||
DWORD RemoteHook(__out SIZE_T *lpnHookId, __out LPVOID *lplpCallOriginal, __in HANDLE hProcess,
|
||||
__in LPVOID lpProcToHook, __in LPVOID lpNewProcAddr, __in DWORD dwFlags);
|
||||
DWORD RemoteHook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in HANDLE hProcess, __in DWORD dwFlags);
|
||||
DWORD RemoteHook(__inout LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in HANDLE hProcess, __in DWORD dwFlags);
|
||||
|
||||
DWORD Unhook(__in SIZE_T nHookId);
|
||||
DWORD Unhook(__in HOOK_INFO aHookInfo[], __in SIZE_T nCount);
|
||||
DWORD Unhook(__in LPHOOK_INFO aHookInfo[], __in SIZE_T nCount);
|
||||
VOID UnhookProcess(__in DWORD dwPid);
|
||||
VOID UnhookAll();
|
||||
|
||||
//NOTE: The following 2 (two) methods will remove the hooks from the internal list of hooks but the original
|
||||
// hook(s) will remain active.
|
||||
DWORD RemoveHook(__in SIZE_T nHookId, BOOL bDisable);
|
||||
DWORD RemoveHook(__in HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bDisable);
|
||||
DWORD RemoveHook(__in LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bDisable);
|
||||
|
||||
DWORD EnableHook(__in SIZE_T nHookId, __in BOOL bEnable);
|
||||
DWORD EnableHook(__in HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bEnable);
|
||||
DWORD EnableHook(__in LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bEnable);
|
||||
|
||||
DWORD SetSuspendThreadsWhileHooking(__in BOOL bEnable);
|
||||
BOOL GetSuspendThreadsWhileHooking();
|
||||
|
||||
DWORD SetEnableDebugOutput(__in BOOL bEnable);
|
||||
BOOL GetEnableDebugOutput();
|
||||
|
||||
void* __cdecl operator new(__in size_t nSize);
|
||||
void* __cdecl operator new[](__in size_t nSize);
|
||||
void* __cdecl operator new(__in size_t nSize, __inout void* lpInPlace);
|
||||
void __cdecl operator delete(__inout void* p);
|
||||
void __cdecl operator delete[](__inout void* p);
|
||||
#if _MSC_VER >= 1200
|
||||
void __cdecl operator delete(__inout void* p, __inout void* lpPlace);
|
||||
#endif //_MSC_VER >= 1200
|
||||
|
||||
private:
|
||||
DWORD HookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags);
|
||||
DWORD UnhookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in DWORD dwFlags);
|
||||
DWORD RemoveHookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in BOOL bDisable, __in DWORD dwFlags);
|
||||
DWORD EnableHookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in BOOL bEnable, __in DWORD dwFlags);
|
||||
|
||||
private:
|
||||
LPVOID lpInternals;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
||||
namespace NktHookLibHelpers {
|
||||
|
||||
//NOTE: See "BuildNtSysCalls" below
|
||||
typedef struct tagSYSCALLDEF {
|
||||
LPSTR szNtApiNameA;
|
||||
SIZE_T nOffset;
|
||||
} SYSCALLDEF, *LPSYSCALLDEF;
|
||||
|
||||
//--------------------------------
|
||||
|
||||
//NOTE: See "SetApiResolverCallback" below
|
||||
typedef LPVOID (__stdcall *lpfnInternalApiResolver)(__in_z LPCSTR szApiNameA, __in LPVOID lpUserParam);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
HINSTANCE GetModuleBaseAddress(__in_z LPCWSTR szDllNameW);
|
||||
LPVOID GetProcedureAddress(__in HINSTANCE hDll, __in LPCSTR szProcNameA);
|
||||
|
||||
HINSTANCE GetRemoteModuleBaseAddress(__in HANDLE hProcess, __in_z LPCWSTR szDllNameW, __in BOOL bScanMappedImages);
|
||||
LPVOID GetRemoteProcedureAddress(__in HANDLE hProcess, __in HINSTANCE hDll, __in_z LPCSTR szProcNameA);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
int sprintf_s(__out_z char *lpDest, __in size_t nMaxCount, __in_z const char *szFormatA, ...);
|
||||
int vsnprintf(__out_z char *lpDest, __in size_t nMaxCount, __in_z const char *szFormatA, __in va_list lpArgList);
|
||||
|
||||
//only on XP or later
|
||||
int swprintf_s(__out_z wchar_t *lpDest, __in size_t nMaxCount, __in_z const wchar_t *szFormatW, ...);
|
||||
int vsnwprintf(__out_z wchar_t *lpDest, __in size_t nMaxCount, __in_z const wchar_t *szFormatW, __in va_list lpArgList);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
//Returns a PROCESSOR_ARCHITECTURE_xxx value or -1 on error.
|
||||
LONG GetProcessorArchitecture();
|
||||
|
||||
HANDLE OpenProcess(__in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in DWORD dwProcessId);
|
||||
HANDLE OpenThread(__in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in DWORD dwThreadId);
|
||||
|
||||
LONG GetProcessPlatform(__in HANDLE hProcess);
|
||||
|
||||
SIZE_T ReadMem(__in HANDLE hProcess, __out LPVOID lpDest, __in LPVOID lpSrc, __in SIZE_T nBytesCount);
|
||||
BOOL WriteMem(__in HANDLE hProcess, __out LPVOID lpDest, __in LPVOID lpSrc, __in SIZE_T nBytesCount);
|
||||
|
||||
LONG GetThreadPriority(__in HANDLE hThread, __out int *lpnPriority);
|
||||
LONG SetThreadPriority(__in HANDLE hThread, __in int nPriority);
|
||||
|
||||
DWORD GetCurrentThreadId();
|
||||
DWORD GetCurrentProcessId();
|
||||
|
||||
HANDLE GetProcessHeap();
|
||||
LPVOID MemAlloc(__in SIZE_T nSize);
|
||||
VOID MemFree(__in LPVOID lpPtr);
|
||||
|
||||
VOID MemSet(__out void *lpDest, __in int nVal, __in SIZE_T nCount);
|
||||
VOID MemCopy(__out void *lpDest, __in const void *lpSrc, __in SIZE_T nCount);
|
||||
SIZE_T TryMemCopy(__out void *lpDest, __in const void *lpSrc, __in SIZE_T nCount);
|
||||
VOID MemMove(__out void *lpDest, __in const void *lpSrc, __in SIZE_T nCount);
|
||||
int MemCompare(__in const void *lpBuf1, __in const void *lpBuf2, __in SIZE_T nCount);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
VOID DebugPrint(__in LPCSTR szFormatA, ...);
|
||||
VOID DebugVPrint(__in LPCSTR szFormatA, __in va_list argptr);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
SIZE_T GetInstructionLength(__in LPVOID lpAddr, __in SIZE_T nSize, __in BYTE nPlatformBits,
|
||||
__out_opt BOOL *lpbIsMemOp=NULL, __out_z_opt LPSTR szBufA=NULL, __in SIZE_T nBufLen=0);
|
||||
|
||||
//NOTE: When NktHookLib is initialized, it tries to locate needed ntdll's apis by scanning process' modules.
|
||||
// If you want to override an api call, use this method to set the resolver address. LPVOID returned by
|
||||
// the callback must have the same definition and calling convention than the one in ntdll. Return NULL
|
||||
// if you want NktHookLib to use the real ntdll api.
|
||||
VOID SetInternalApiResolverCallback(__in lpfnInternalApiResolver fnInternalApiResolver, __in LPVOID lpUserParam);
|
||||
|
||||
//This function generates a relocatable byte code with a copy of the original SysCall routine for each passes
|
||||
//ntdll api. The code is created based on the original ntdll.dll image file on disk located on System32 or SysWow64,
|
||||
//depending on the target platform.
|
||||
//
|
||||
//Useful for doing direct calls to low level apis bypassing third party hooks (like Chrome navigator does). Also, you
|
||||
//can pass the generated code to another process. You can generate the code with this method, pass it to another
|
||||
//process and then use SetApiResolverCallback above.
|
||||
//
|
||||
//NOTE: Not all NtXXX apis are SysCalls. Trying to generate code for a non-syscall api may generate an unexpected
|
||||
// behavior.
|
||||
// If 'lpCode' is NULL, the needed space is returned. Although syscalls uses less than 32 bytes, a maximum of 256
|
||||
// bytes are supported for each requested api. You can safety allocate a block of 256*nDefsCount bytes to hold
|
||||
// the generated code.
|
||||
DWORD BuildNtSysCalls(__in LPSYSCALLDEF lpDefs, __in SIZE_T nDefsCount, __in SIZE_T nPlatform,
|
||||
__out_opt LPVOID lpCode, __out SIZE_T *lpnCodeSize);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
//NOTE: Return 0xFFFFFFFF if remote thread is not accessible
|
||||
DWORD GetWin32LastError(__in_opt HANDLE hThread=NULL);
|
||||
BOOL SetWin32LastError(__in DWORD dwErrorCode, __in_opt HANDLE hThread=NULL);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
BOOL GetOsVersion(__out_opt LPDWORD lpdwVerMajor=NULL, __out_opt LPDWORD lpdwVerMinor=NULL,
|
||||
__out_opt LPDWORD lpdwBuildNumber=NULL);
|
||||
|
||||
//--------------------------------
|
||||
|
||||
//NOTE: CreateProcessWithDllW and related functions returns the Win32 error code directly. NOERROR => Success.
|
||||
//
|
||||
// If "szDllNameW" string ends with 'x86.dll', 'x64.dll', '32.dll', '64.dll', the dll name will be adjusted
|
||||
// in order to match the process platform. I.e.: "mydll_x86.dll" will become "mydll_x64.dll" on 64-bit processes.
|
||||
DWORD CreateProcessWithDllW(__in_z_opt LPCWSTR lpApplicationName, __inout_z_opt LPWSTR lpCommandLine,
|
||||
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles,
|
||||
__in DWORD dwCreationFlags, __in_z_opt LPCWSTR lpEnvironment,
|
||||
__in_z_opt LPCWSTR lpCurrentDirectory, __in LPSTARTUPINFOW lpStartupInfo,
|
||||
__out LPPROCESS_INFORMATION lpProcessInformation, __in_z LPCWSTR szDllNameW,
|
||||
__in_opt HANDLE hSignalCompleted=NULL, __in_z_opt LPCSTR szInitFunctionA=NULL,
|
||||
__in_opt LPVOID lpInitFuncParams=NULL, __in_opt ULONG nInitFuncParamsSize=0);
|
||||
|
||||
DWORD CreateProcessWithLogonAndDllW(__in_z LPCWSTR lpUsername, __in_z_opt LPCWSTR lpDomain, __in_z LPCWSTR lpPassword,
|
||||
__in DWORD dwLogonFlags, __in_opt LPCWSTR lpApplicationName,
|
||||
__inout_opt LPWSTR lpCommandLine, __in DWORD dwCreationFlags,
|
||||
__in_z_opt LPCWSTR lpEnvironment, __in_z_opt LPCWSTR lpCurrentDirectory,
|
||||
__in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation,
|
||||
__in_z LPCWSTR szDllNameW, __in_opt HANDLE hSignalCompleted=NULL,
|
||||
__in_z_opt LPCSTR szInitFunctionA=NULL, __in_opt LPVOID lpInitFuncParams=NULL,
|
||||
__in_opt ULONG nInitFuncParamsSize=0);
|
||||
|
||||
DWORD CreateProcessWithTokenAndDllW(__in HANDLE hToken, __in DWORD dwLogonFlags, __in_z_opt LPCWSTR lpApplicationName,
|
||||
__inout_opt LPWSTR lpCommandLine, __in DWORD dwCreationFlags,
|
||||
__in_z_opt LPCWSTR lpEnvironment, __in_z_opt LPCWSTR lpCurrentDirectory,
|
||||
__in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation,
|
||||
__in_z LPCWSTR szDllNameW, __in_opt HANDLE hSignalCompleted=NULL,
|
||||
__in_z_opt LPCSTR szInitFunctionA=NULL, __in_opt LPVOID lpInitFuncParams=NULL,
|
||||
__in_opt ULONG nInitFuncParamsSize=0);
|
||||
|
||||
DWORD InjectDllByPidW(__in DWORD dwPid, __in_z LPCWSTR szDllNameW, __in_z_opt LPCSTR szInitFunctionA=NULL,
|
||||
__in_opt DWORD dwProcessInitWaitTimeoutMs=5000, __out_opt LPHANDLE lphInjectorThread=NULL,
|
||||
__in_opt LPVOID lpInitFuncParams=NULL, __in_opt ULONG nInitFuncParamsSize=0);
|
||||
|
||||
DWORD InjectDllByHandleW(__in HANDLE hProcess, __in_z LPCWSTR szDllNameW, __in_z_opt LPCSTR szInitFunctionA=NULL,
|
||||
__in_opt DWORD dwProcessInitWaitTimeoutMs=5000, __out_opt LPHANDLE lphInjectorThread=NULL,
|
||||
__in_opt LPVOID lpInitFuncParams=NULL, __in_opt ULONG nInitFuncParamsSize=0);
|
||||
|
||||
} //NktHookLibHelpers
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
||||
#endif //_NKTHOOKLIB
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "SDL_power.h"
|
||||
#include "SDL_render.h"
|
||||
#include "SDL_rwops.h"
|
||||
#include "SDL_sensor.h"
|
||||
#include "SDL_shape.h"
|
||||
#include "SDL_system.h"
|
||||
#include "SDL_thread.h"
|
||||
@@ -80,10 +81,11 @@ extern "C" {
|
||||
#define SDL_INIT_HAPTIC 0x00001000u
|
||||
#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
|
||||
#define SDL_INIT_EVENTS 0x00004000u
|
||||
#define SDL_INIT_SENSOR 0x00008000u
|
||||
#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */
|
||||
#define SDL_INIT_EVERYTHING ( \
|
||||
SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
|
||||
SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
|
||||
SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \
|
||||
)
|
||||
/* @} */
|
||||
|
||||
|
||||
@@ -140,7 +140,8 @@ typedef Uint16 SDL_AudioFormat;
|
||||
#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
|
||||
#define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
|
||||
#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
|
||||
#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
|
||||
#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0x00000008
|
||||
#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)
|
||||
/* @} */
|
||||
|
||||
/* @} *//* Audio flags */
|
||||
|
||||
@@ -82,6 +82,9 @@ typedef unsigned int uintptr_t;
|
||||
#define HAVE_DSOUND_H 1
|
||||
#define HAVE_DXGI_H 1
|
||||
#define HAVE_XINPUT_H 1
|
||||
#define HAVE_MMDEVICEAPI_H 1
|
||||
#define HAVE_AUDIOCLIENT_H 1
|
||||
#define HAVE_ENDPOINTVOLUME_H 1
|
||||
|
||||
/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
|
||||
#ifdef HAVE_LIBC
|
||||
@@ -139,6 +142,8 @@ typedef unsigned int uintptr_t;
|
||||
#define HAVE__COPYSIGN 1
|
||||
#define HAVE_COS 1
|
||||
#define HAVE_COSF 1
|
||||
#define HAVE_EXP 1
|
||||
#define HAVE_EXPF 1
|
||||
#define HAVE_FABS 1
|
||||
#define HAVE_FABSF 1
|
||||
#define HAVE_FLOOR 1
|
||||
@@ -188,9 +193,13 @@ typedef unsigned int uintptr_t;
|
||||
/* Enable various input drivers */
|
||||
#define SDL_JOYSTICK_DINPUT 1
|
||||
#define SDL_JOYSTICK_XINPUT 1
|
||||
#define SDL_JOYSTICK_HIDAPI 1
|
||||
#define SDL_HAPTIC_DINPUT 1
|
||||
#define SDL_HAPTIC_XINPUT 1
|
||||
|
||||
/* Enable the dummy sensor driver */
|
||||
#define SDL_SENSOR_DUMMY 1
|
||||
|
||||
/* Enable various shared object loading systems */
|
||||
#define SDL_LOADSO_WINDOWS 1
|
||||
|
||||
|
||||
@@ -51,16 +51,19 @@
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#ifdef __ALTIVEC__
|
||||
#if HAVE_ALTIVEC_H && !defined(__APPLE_ALTIVEC__) && !defined(SDL_DISABLE_ALTIVEC_H)
|
||||
#if defined(HAVE_ALTIVEC_H) && !defined(__APPLE_ALTIVEC__) && !defined(SDL_DISABLE_ALTIVEC_H)
|
||||
#include <altivec.h>
|
||||
#undef pixel
|
||||
#undef bool
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__ARM_NEON__) && !defined(SDL_DISABLE_ARM_NEON_H)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
#if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
|
||||
#include <mm3dnow.h>
|
||||
#endif
|
||||
#if HAVE_IMMINTRIN_H && !defined(SDL_DISABLE_IMMINTRIN_H)
|
||||
#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
|
||||
#include <immintrin.h>
|
||||
#else
|
||||
#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H)
|
||||
@@ -159,6 +162,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void);
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
|
||||
|
||||
/**
|
||||
* This function returns true if the CPU has AVX-512F (foundation) features.
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
|
||||
|
||||
/**
|
||||
* This function returns true if the CPU has NEON (ARM SIMD) features.
|
||||
*/
|
||||
@@ -169,7 +177,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
|
||||
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -85,6 +85,9 @@ typedef enum
|
||||
Called on Android in onResume()
|
||||
*/
|
||||
|
||||
/* Display events */
|
||||
SDL_DISPLAYEVENT = 0x150, /**< Display state change */
|
||||
|
||||
/* Window events */
|
||||
SDL_WINDOWEVENT = 0x200, /**< Window state change */
|
||||
SDL_SYSWMEVENT, /**< System specific event */
|
||||
@@ -144,6 +147,9 @@ typedef enum
|
||||
SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
|
||||
SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */
|
||||
|
||||
/* Sensor events */
|
||||
SDL_SENSORUPDATE = 0x1200, /**< A sensor was updated */
|
||||
|
||||
/* Render events */
|
||||
SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
|
||||
SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
|
||||
@@ -168,6 +174,21 @@ typedef struct SDL_CommonEvent
|
||||
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
|
||||
} SDL_CommonEvent;
|
||||
|
||||
/**
|
||||
* \brief Display state change event data (event.display.*)
|
||||
*/
|
||||
typedef struct SDL_DisplayEvent
|
||||
{
|
||||
Uint32 type; /**< ::SDL_DISPLAYEVENT */
|
||||
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
|
||||
Uint32 display; /**< The associated display index */
|
||||
Uint8 event; /**< ::SDL_DisplayEventID */
|
||||
Uint8 padding1;
|
||||
Uint8 padding2;
|
||||
Uint8 padding3;
|
||||
Sint32 data1; /**< event dependent data */
|
||||
} SDL_DisplayEvent;
|
||||
|
||||
/**
|
||||
* \brief Window state change event data (event.window.*)
|
||||
*/
|
||||
@@ -471,6 +492,17 @@ typedef struct SDL_DropEvent
|
||||
} SDL_DropEvent;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sensor event structure (event.sensor.*)
|
||||
*/
|
||||
typedef struct SDL_SensorEvent
|
||||
{
|
||||
Uint32 type; /**< ::SDL_SENSORUPDATE */
|
||||
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
|
||||
Sint32 which; /**< The instance ID of the sensor */
|
||||
float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
|
||||
} SDL_SensorEvent;
|
||||
|
||||
/**
|
||||
* \brief The "quit requested" event
|
||||
*/
|
||||
@@ -526,6 +558,7 @@ typedef union SDL_Event
|
||||
{
|
||||
Uint32 type; /**< Event type, shared with all events */
|
||||
SDL_CommonEvent common; /**< Common event data */
|
||||
SDL_DisplayEvent display; /**< Window event data */
|
||||
SDL_WindowEvent window; /**< Window event data */
|
||||
SDL_KeyboardEvent key; /**< Keyboard event data */
|
||||
SDL_TextEditingEvent edit; /**< Text editing event data */
|
||||
@@ -542,6 +575,7 @@ typedef union SDL_Event
|
||||
SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
|
||||
SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
|
||||
SDL_AudioDeviceEvent adevice; /**< Audio device event data */
|
||||
SDL_SensorEvent sensor; /**< Sensor event data */
|
||||
SDL_QuitEvent quit; /**< Quit request event data */
|
||||
SDL_UserEvent user; /**< Custom event data */
|
||||
SDL_SysWMEvent syswm; /**< System dependent window event data */
|
||||
|
||||
@@ -175,6 +175,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsGameController(int joystick_index);
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index);
|
||||
|
||||
/**
|
||||
* Get the mapping of a game controller.
|
||||
* This can be called before any controllers are opened.
|
||||
*
|
||||
* \return the mapping string. Must be freed with SDL_free(). Returns NULL if no mapping is available
|
||||
*/
|
||||
extern DECLSPEC char *SDLCALL SDL_GameControllerMappingForDeviceIndex(int joystick_index);
|
||||
|
||||
/**
|
||||
* Open a game controller for use.
|
||||
* The index passed as an argument refers to the N'th game controller on the system.
|
||||
@@ -196,6 +204,13 @@ extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller);
|
||||
|
||||
/**
|
||||
* Get the player index of an opened game controller, or -1 if it's not available
|
||||
*
|
||||
* For XInput controllers this returns the XInput user index.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller);
|
||||
|
||||
/**
|
||||
* Get the USB vendor ID of an opened controller, if available.
|
||||
* If the vendor ID isn't available this function returns 0.
|
||||
@@ -345,6 +360,19 @@ SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller,
|
||||
extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController *gamecontroller,
|
||||
SDL_GameControllerButton button);
|
||||
|
||||
/**
|
||||
* Trigger a rumble effect
|
||||
* Each call to this function cancels any previous rumble effect, and calling it with 0 intensity stops any rumbling.
|
||||
*
|
||||
* \param gamecontroller The controller to vibrate
|
||||
* \param low_frequency_rumble The intensity of the low frequency (left) rumble motor, from 0 to 0xFFFF
|
||||
* \param high_frequency_rumble The intensity of the high frequency (right) rumble motor, from 0 to 0xFFFF
|
||||
* \param duration_ms The duration of the rumble effect, in milliseconds
|
||||
*
|
||||
* \return 0, or -1 if rumble isn't supported on this joystick
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
|
||||
|
||||
/**
|
||||
* Close a controller previously opened with SDL_GameControllerOpen().
|
||||
*/
|
||||
|
||||
@@ -117,6 +117,17 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* FIXME: For SDL 2.1, adjust all the magnitude variables to be Uint16 (0xFFFF).
|
||||
*
|
||||
* At the moment the magnitude variables are mixed between signed/unsigned, and
|
||||
* it is also not made clear that ALL of those variables expect a max of 0x7FFF.
|
||||
*
|
||||
* Some platforms may have higher precision than that (Linux FF, Windows XInput)
|
||||
* so we should fix the inconsistency in favor of higher possible precision,
|
||||
* adjusting for platforms that use different scales.
|
||||
* -flibit
|
||||
*/
|
||||
|
||||
/**
|
||||
* \typedef SDL_Haptic
|
||||
*
|
||||
@@ -656,8 +667,8 @@ typedef struct SDL_HapticRamp
|
||||
* This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
|
||||
*
|
||||
* The Left/Right effect is used to explicitly control the large and small
|
||||
* motors, commonly found in modern game controllers. One motor is high
|
||||
* frequency, the other is low frequency.
|
||||
* motors, commonly found in modern game controllers. The small (right) motor
|
||||
* is high frequency, and the large (left) motor is low frequency.
|
||||
*
|
||||
* \sa SDL_HAPTIC_LEFTRIGHT
|
||||
* \sa SDL_HapticEffect
|
||||
@@ -668,7 +679,7 @@ typedef struct SDL_HapticLeftRight
|
||||
Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */
|
||||
|
||||
/* Replay */
|
||||
Uint32 length; /**< Duration of the effect. */
|
||||
Uint32 length; /**< Duration of the effect in milliseconds. */
|
||||
|
||||
/* Rumble */
|
||||
Uint16 large_magnitude; /**< Control of the large controller motor. */
|
||||
|
||||
@@ -262,6 +262,16 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD"
|
||||
|
||||
/**
|
||||
* \brief A variable setting the double click time, in milliseconds.
|
||||
*/
|
||||
#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME"
|
||||
|
||||
/**
|
||||
* \brief A variable setting the double click radius, in pixels.
|
||||
*/
|
||||
#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS"
|
||||
|
||||
/**
|
||||
* \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode
|
||||
*/
|
||||
@@ -329,7 +339,7 @@ extern "C" {
|
||||
#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling which orientations are allowed on iOS.
|
||||
* \brief A variable controlling which orientations are allowed on iOS/Android.
|
||||
*
|
||||
* In some circumstances it is necessary to be able to explicitly control
|
||||
* which UI orientations are allowed.
|
||||
@@ -465,6 +475,88 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether the HIDAPI joystick drivers should be used.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - HIDAPI drivers are not used
|
||||
* "1" - HIDAPI drivers are used (the default)
|
||||
*
|
||||
* This variable is the default for all drivers, but can be overridden by the hints for specific drivers below.
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - HIDAPI driver is not used
|
||||
* "1" - HIDAPI driver is used
|
||||
*
|
||||
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - extended reports are not enabled (the default)
|
||||
* "1" - extended reports
|
||||
*
|
||||
* Extended input reports allow rumble on Bluetooth PS4 controllers, but
|
||||
* break DirectInput handling for applications that don't use SDL.
|
||||
*
|
||||
* Once extended reports are enabled, they can not be disabled without
|
||||
* power cycling the controller.
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether the HIDAPI driver for Steam Controllers should be used.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - HIDAPI driver is not used
|
||||
* "1" - HIDAPI driver is used
|
||||
*
|
||||
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - HIDAPI driver is not used
|
||||
* "1" - HIDAPI driver is used
|
||||
*
|
||||
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - HIDAPI driver is not used
|
||||
* "1" - HIDAPI driver is used
|
||||
*
|
||||
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
|
||||
*/
|
||||
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
|
||||
|
||||
/**
|
||||
* \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
* "0" - Do not scan for Steam Controllers
|
||||
* "1" - Scan for Steam Controllers (the default)
|
||||
*
|
||||
* The default value is "1". This hint must be set before initializing the joystick subsystem.
|
||||
*/
|
||||
#define SDL_HINT_ENABLE_STEAM_CONTROLLERS "SDL_ENABLE_STEAM_CONTROLLERS"
|
||||
|
||||
|
||||
/**
|
||||
* \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it.
|
||||
* This is a debugging aid for developers and not expected to be used by end users. The default is "1"
|
||||
@@ -527,6 +619,10 @@ extern "C" {
|
||||
* This is specially useful if you build SDL against a non glibc libc library (such as musl) which
|
||||
* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
|
||||
* Support for this hint is currently available only in the pthread, Windows, and PSP backend.
|
||||
*
|
||||
* Instead of this hint, in 2.0.9 and later, you can use
|
||||
* SDL_CreateThreadWithStackSize(). This hint only works with the classic
|
||||
* SDL_CreateThread().
|
||||
*/
|
||||
#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE"
|
||||
|
||||
@@ -752,6 +848,23 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH"
|
||||
|
||||
/**
|
||||
* \brief A variable to control whether we trap the Android back button to handle it manually.
|
||||
* This is necessary for the right mouse button to work on some Android devices, or
|
||||
* to be able to trap the back button for use in your code reliably. If set to true,
|
||||
* the back button will show up as an SDL_KEYDOWN / SDL_KEYUP pair with a keycode of
|
||||
* SDL_SCANCODE_AC_BACK.
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
* "0" - Back button will be handled as usual for system. (default)
|
||||
* "1" - Back button will be trapped, allowing you to handle the key press
|
||||
* manually. (This will also let right mouse click work on systems
|
||||
* where the right mouse button functions as back.)
|
||||
*
|
||||
* The value of this hint is used at runtime, so it can be changed at any time.
|
||||
*/
|
||||
#define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON"
|
||||
|
||||
/**
|
||||
* \brief A variable to control whether the return key on the soft keyboard
|
||||
* should hide the soft keyboard on Android and iOS.
|
||||
|
||||
@@ -97,10 +97,10 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
SDL_JOYSTICK_POWER_UNKNOWN = -1,
|
||||
SDL_JOYSTICK_POWER_EMPTY,
|
||||
SDL_JOYSTICK_POWER_LOW,
|
||||
SDL_JOYSTICK_POWER_MEDIUM,
|
||||
SDL_JOYSTICK_POWER_FULL,
|
||||
SDL_JOYSTICK_POWER_EMPTY, /* <= 5% */
|
||||
SDL_JOYSTICK_POWER_LOW, /* <= 20% */
|
||||
SDL_JOYSTICK_POWER_MEDIUM, /* <= 70% */
|
||||
SDL_JOYSTICK_POWER_FULL, /* <= 100% */
|
||||
SDL_JOYSTICK_POWER_WIRED,
|
||||
SDL_JOYSTICK_POWER_MAX
|
||||
} SDL_JoystickPowerLevel;
|
||||
@@ -132,6 +132,12 @@ extern DECLSPEC int SDLCALL SDL_NumJoysticks(void);
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index);
|
||||
|
||||
/**
|
||||
* Get the player index of a joystick, or -1 if it's not available
|
||||
* This can be called before any joysticks are opened.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_JoystickGetDevicePlayerIndex(int device_index);
|
||||
|
||||
/**
|
||||
* Return the GUID for the joystick at this index
|
||||
* This can be called before any joysticks are opened.
|
||||
@@ -194,6 +200,13 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick * joystick);
|
||||
|
||||
/**
|
||||
* Get the player index of an opened joystick, or -1 if it's not available
|
||||
*
|
||||
* For XInput controllers this returns the XInput user index.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick);
|
||||
|
||||
/**
|
||||
* Return the GUID for this opened joystick
|
||||
*/
|
||||
@@ -361,6 +374,19 @@ extern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick * joystick,
|
||||
extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick * joystick,
|
||||
int button);
|
||||
|
||||
/**
|
||||
* Trigger a rumble effect
|
||||
* Each call to this function cancels any previous rumble effect, and calling it with 0 intensity stops any rumbling.
|
||||
*
|
||||
* \param joystick The joystick to vibrate
|
||||
* \param low_frequency_rumble The intensity of the low frequency (left) rumble motor, from 0 to 0xFFFF
|
||||
* \param high_frequency_rumble The intensity of the high frequency (right) rumble motor, from 0 to 0xFFFF
|
||||
* \param duration_ms The duration of the rumble effect, in milliseconds
|
||||
*
|
||||
* \return 0, or -1 if rumble isn't supported on this joystick
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
|
||||
|
||||
/**
|
||||
* Close a joystick previously opened with SDL_JoystickOpen().
|
||||
*/
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#define SDL_REVISION "hg-11914:f1084c419f33"
|
||||
#define SDL_REVISION_NUMBER 11914
|
||||
#define SDL_REVISION "hg-12373:8feb5da6f2fb"
|
||||
#define SDL_REVISION_NUMBER 12373
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <[email protected]>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_sensor.h
|
||||
*
|
||||
* Include file for SDL sensor event handling
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SDL_sensor_h
|
||||
#define _SDL_sensor_h
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_error.h"
|
||||
|
||||
#include "begin_code.h"
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SDL_sensor.h
|
||||
*
|
||||
* In order to use these functions, SDL_Init() must have been called
|
||||
* with the ::SDL_INIT_SENSOR flag. This causes SDL to scan the system
|
||||
* for sensors, and load appropriate drivers.
|
||||
*/
|
||||
|
||||
struct _SDL_Sensor;
|
||||
typedef struct _SDL_Sensor SDL_Sensor;
|
||||
|
||||
/**
|
||||
* This is a unique ID for a sensor for the time it is connected to the system,
|
||||
* and is never reused for the lifetime of the application.
|
||||
*
|
||||
* The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
|
||||
*/
|
||||
typedef Sint32 SDL_SensorID;
|
||||
|
||||
/* The different sensors defined by SDL
|
||||
*
|
||||
* Additional sensors may be available, using platform dependent semantics.
|
||||
*
|
||||
* Hare are the additional Android sensors:
|
||||
* https://developer.android.com/reference/android/hardware/SensorEvent.html#values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */
|
||||
SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */
|
||||
SDL_SENSOR_ACCEL, /**< Accelerometer */
|
||||
SDL_SENSOR_GYRO /**< Gyroscope */
|
||||
} SDL_SensorType;
|
||||
|
||||
/**
|
||||
* Accelerometer sensor
|
||||
*
|
||||
* The accelerometer returns the current acceleration in SI meters per
|
||||
* second squared. This includes gravity, so a device at rest will have
|
||||
* an acceleration of SDL_STANDARD_GRAVITY straight down.
|
||||
*
|
||||
* values[0]: Acceleration on the x axis
|
||||
* values[1]: Acceleration on the y axis
|
||||
* values[2]: Acceleration on the z axis
|
||||
*
|
||||
* For phones held in portrait mode, the axes are defined as follows:
|
||||
* -X ... +X : left ... right
|
||||
* -Y ... +Y : bottom ... top
|
||||
* -Z ... +Z : farther ... closer
|
||||
*
|
||||
* The axis data is not changed when the phone is rotated.
|
||||
*
|
||||
* \sa SDL_GetDisplayOrientation()
|
||||
*/
|
||||
#define SDL_STANDARD_GRAVITY 9.80665f
|
||||
|
||||
/**
|
||||
* Gyroscope sensor
|
||||
*
|
||||
* The gyroscope returns the current rate of rotation in radians per second.
|
||||
* The rotation is positive in the counter-clockwise direction. That is,
|
||||
* an observer looking from a positive location on one of the axes would
|
||||
* see positive rotation on that axis when it appeared to be rotating
|
||||
* counter-clockwise.
|
||||
*
|
||||
* values[0]: Angular speed around the x axis
|
||||
* values[1]: Angular speed around the y axis
|
||||
* values[2]: Angular speed around the z axis
|
||||
*
|
||||
* For phones held in portrait mode, the axes are defined as follows:
|
||||
* -X ... +X : left ... right
|
||||
* -Y ... +Y : bottom ... top
|
||||
* -Z ... +Z : farther ... closer
|
||||
*
|
||||
* The axis data is not changed when the phone is rotated.
|
||||
*
|
||||
* \sa SDL_GetDisplayOrientation()
|
||||
*/
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
/**
|
||||
* \brief Count the number of sensors attached to the system right now
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_NumSensors(void);
|
||||
|
||||
/**
|
||||
* \brief Get the implementation dependent name of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor name, or NULL if device_index is out of range.
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_SensorGetDeviceName(int device_index);
|
||||
|
||||
/**
|
||||
* \brief Get the type of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor type, or SDL_SENSOR_INVALID if device_index is out of range.
|
||||
*/
|
||||
extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetDeviceType(int device_index);
|
||||
|
||||
/**
|
||||
* \brief Get the platform dependent type of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor platform dependent type, or -1 if device_index is out of range.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SensorGetDeviceNonPortableType(int device_index);
|
||||
|
||||
/**
|
||||
* \brief Get the instance ID of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor instance ID, or -1 if device_index is out of range.
|
||||
*/
|
||||
extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetDeviceInstanceID(int device_index);
|
||||
|
||||
/**
|
||||
* \brief Open a sensor for use.
|
||||
*
|
||||
* The index passed as an argument refers to the N'th sensor on the system.
|
||||
*
|
||||
* \return A sensor identifier, or NULL if an error occurred.
|
||||
*/
|
||||
extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorOpen(int device_index);
|
||||
|
||||
/**
|
||||
* Return the SDL_Sensor associated with an instance id.
|
||||
*/
|
||||
extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorFromInstanceID(SDL_SensorID instance_id);
|
||||
|
||||
/**
|
||||
* \brief Get the implementation dependent name of a sensor.
|
||||
*
|
||||
* \return The sensor name, or NULL if the sensor is NULL.
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_SensorGetName(SDL_Sensor *sensor);
|
||||
|
||||
/**
|
||||
* \brief Get the type of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor type, or SDL_SENSOR_INVALID if the sensor is NULL.
|
||||
*/
|
||||
extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetType(SDL_Sensor *sensor);
|
||||
|
||||
/**
|
||||
* \brief Get the platform dependent type of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor platform dependent type, or -1 if the sensor is NULL.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SensorGetNonPortableType(SDL_Sensor *sensor);
|
||||
|
||||
/**
|
||||
* \brief Get the instance ID of a sensor.
|
||||
*
|
||||
* This can be called before any sensors are opened.
|
||||
*
|
||||
* \return The sensor instance ID, or -1 if the sensor is NULL.
|
||||
*/
|
||||
extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetInstanceID(SDL_Sensor *sensor);
|
||||
|
||||
/**
|
||||
* Get the current state of an opened sensor.
|
||||
*
|
||||
* The number of values and interpretation of the data is sensor dependent.
|
||||
*
|
||||
* \param sensor The sensor to query
|
||||
* \param data A pointer filled with the current sensor state
|
||||
* \param num_values The number of values to write to data
|
||||
*
|
||||
* \return 0 or -1 if an error occurred.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values);
|
||||
|
||||
/**
|
||||
* Close a sensor previously opened with SDL_SensorOpen()
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_SensorClose(SDL_Sensor * sensor);
|
||||
|
||||
/**
|
||||
* Update the current state of the open sensors.
|
||||
*
|
||||
* This is called automatically by the event loop if sensor events are enabled.
|
||||
*
|
||||
* This needs to be called from the thread that initialized the sensor subsystem.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_SensorUpdate(void);
|
||||
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
#include "close_code.h"
|
||||
|
||||
#endif /* _SDL_sensor_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -86,6 +86,28 @@
|
||||
#ifdef HAVE_FLOAT_H
|
||||
# include <float.h>
|
||||
#endif
|
||||
#if defined(HAVE_ALLOCA) && !defined(alloca)
|
||||
# if defined(HAVE_ALLOCA_H)
|
||||
# include <alloca.h>
|
||||
# elif defined(__GNUC__)
|
||||
# define alloca __builtin_alloca
|
||||
# elif defined(_MSC_VER)
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
# elif defined(__WATCOMC__)
|
||||
# include <malloc.h>
|
||||
# elif defined(__BORLANDC__)
|
||||
# include <malloc.h>
|
||||
# elif defined(__DMC__)
|
||||
# include <stdlib.h>
|
||||
# elif defined(__AIX__)
|
||||
#pragma alloca
|
||||
# elif defined(__MRC__)
|
||||
void *alloca(unsigned);
|
||||
# else
|
||||
char *alloca();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The number of elements in an array.
|
||||
@@ -328,28 +350,6 @@ SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int));
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ALLOCA) && !defined(alloca)
|
||||
# if defined(HAVE_ALLOCA_H)
|
||||
# include <alloca.h>
|
||||
# elif defined(__GNUC__)
|
||||
# define alloca __builtin_alloca
|
||||
# elif defined(_MSC_VER)
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
# elif defined(__WATCOMC__)
|
||||
# include <malloc.h>
|
||||
# elif defined(__BORLANDC__)
|
||||
# include <malloc.h>
|
||||
# elif defined(__DMC__)
|
||||
# include <stdlib.h>
|
||||
# elif defined(__AIX__)
|
||||
#pragma alloca
|
||||
# elif defined(__MRC__)
|
||||
void *alloca(unsigned);
|
||||
# else
|
||||
char *alloca();
|
||||
# endif
|
||||
#endif
|
||||
#ifdef HAVE_ALLOCA
|
||||
#define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count))
|
||||
#define SDL_stack_free(data)
|
||||
@@ -445,12 +445,12 @@ SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern DECLSPEC void *SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len);
|
||||
|
||||
extern DECLSPEC void *SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len);
|
||||
extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len);
|
||||
|
||||
extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr);
|
||||
extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr);
|
||||
extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
|
||||
extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
|
||||
@@ -514,6 +514,8 @@ extern DECLSPEC double SDLCALL SDL_copysign(double x, double y);
|
||||
extern DECLSPEC float SDLCALL SDL_copysignf(float x, float y);
|
||||
extern DECLSPEC double SDLCALL SDL_cos(double x);
|
||||
extern DECLSPEC float SDLCALL SDL_cosf(float x);
|
||||
extern DECLSPEC double SDLCALL SDL_exp(double x);
|
||||
extern DECLSPEC float SDLCALL SDL_expf(float x);
|
||||
extern DECLSPEC double SDLCALL SDL_fabs(double x);
|
||||
extern DECLSPEC float SDLCALL SDL_fabsf(float x);
|
||||
extern DECLSPEC double SDLCALL SDL_floor(double x);
|
||||
|
||||
@@ -248,6 +248,13 @@ extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface * surface,
|
||||
extern DECLSPEC int SDLCALL SDL_SetColorKey(SDL_Surface * surface,
|
||||
int flag, Uint32 key);
|
||||
|
||||
/**
|
||||
* \brief Returns whether the surface has a color key
|
||||
*
|
||||
* \return SDL_TRUE if the surface has a color key, or SDL_FALSE if the surface is NULL or has no color key
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_HasColorKey(SDL_Surface * surface);
|
||||
|
||||
/**
|
||||
* \brief Gets the color key (transparent pixel) in a blittable surface.
|
||||
*
|
||||
|
||||
@@ -76,6 +76,18 @@ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *a
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
|
||||
/* Platform specific functions for Linux */
|
||||
#ifdef __LINUX__
|
||||
|
||||
/**
|
||||
\brief Sets the UNIX nice value for a thread, using setpriority() if possible, and RealtimeKit if available.
|
||||
|
||||
\return 0 on success, or -1 on error.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority);
|
||||
|
||||
#endif /* __LINUX__ */
|
||||
|
||||
/* Platform specific functions for iOS */
|
||||
#if defined(__IPHONEOS__) && __IPHONEOS__
|
||||
|
||||
@@ -113,6 +125,21 @@ extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void);
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void);
|
||||
|
||||
/**
|
||||
\brief Return true if the application is running on a Chromebook
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void);
|
||||
|
||||
/**
|
||||
\brief Return true is the application is running on a Samsung DeX docking station
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void);
|
||||
|
||||
/**
|
||||
\brief Trigger the Android system back button behavior.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void);
|
||||
|
||||
/**
|
||||
See the official Android developer guide for more information:
|
||||
http://developer.android.com/guide/topics/data/data-storage.html
|
||||
@@ -236,6 +263,11 @@ extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily();
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
|
||||
/**
|
||||
\brief Return true if the current device is a tablet.
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_IsTablet(void);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -33,12 +33,6 @@
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_version.h"
|
||||
|
||||
#include "begin_code.h"
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file SDL_syswm.h
|
||||
*
|
||||
@@ -110,6 +104,12 @@ typedef void *EGLSurface;
|
||||
#include "SDL_egl.h"
|
||||
#endif
|
||||
|
||||
#include "begin_code.h"
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* These are the various supported windowing subsystems
|
||||
*/
|
||||
|
||||
@@ -54,12 +54,13 @@ typedef unsigned int SDL_TLSID;
|
||||
/**
|
||||
* The SDL thread priority.
|
||||
*
|
||||
* \note On many systems you require special privileges to set high priority.
|
||||
* \note On many systems you require special privileges to set high or time critical priority.
|
||||
*/
|
||||
typedef enum {
|
||||
SDL_THREAD_PRIORITY_LOW,
|
||||
SDL_THREAD_PRIORITY_NORMAL,
|
||||
SDL_THREAD_PRIORITY_HIGH
|
||||
SDL_THREAD_PRIORITY_HIGH,
|
||||
SDL_THREAD_PRIORITY_TIME_CRITICAL
|
||||
} SDL_ThreadPriority;
|
||||
|
||||
/**
|
||||
@@ -105,14 +106,24 @@ SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread);
|
||||
|
||||
extern DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
|
||||
const char *name, const size_t stacksize, void *data,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread);
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread.
|
||||
*/
|
||||
#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
|
||||
#undef SDL_CreateThread
|
||||
#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
|
||||
#undef SDL_CreateThreadWithStackSize
|
||||
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
|
||||
#else
|
||||
#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
|
||||
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
|
||||
#endif
|
||||
|
||||
#elif defined(__OS2__)
|
||||
@@ -132,15 +143,31 @@ extern DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread);
|
||||
extern DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread);
|
||||
#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
|
||||
#undef SDL_CreateThread
|
||||
#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
|
||||
#undef SDL_CreateThreadWithStackSize
|
||||
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
|
||||
#else
|
||||
#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
|
||||
#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)_beginthread, (pfnSDL_CurrentEndThread)_endthread)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Create a thread with a default stack size.
|
||||
*
|
||||
* This is equivalent to calling:
|
||||
* SDL_CreateThreadWithStackSize(fn, name, 0, data);
|
||||
*/
|
||||
extern DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
|
||||
|
||||
/**
|
||||
* Create a thread.
|
||||
*
|
||||
@@ -158,9 +185,17 @@ SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
|
||||
* If a system imposes requirements, SDL will try to munge the string for
|
||||
* it (truncate, etc), but the original string contents will be available
|
||||
* from SDL_GetThreadName().
|
||||
*
|
||||
* The size (in bytes) of the new stack can be specified. Zero means "use
|
||||
* the system default" which might be wildly different between platforms
|
||||
* (x86 Linux generally defaults to eight megabytes, an embedded device
|
||||
* might be a few kilobytes instead).
|
||||
*
|
||||
* In SDL 2.1, stacksize will be folded into the original SDL_CreateThread
|
||||
* function.
|
||||
*/
|
||||
extern DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
|
||||
SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ typedef struct SDL_version
|
||||
*/
|
||||
#define SDL_MAJOR_VERSION 2
|
||||
#define SDL_MINOR_VERSION 0
|
||||
#define SDL_PATCHLEVEL 8
|
||||
#define SDL_PATCHLEVEL 9
|
||||
|
||||
/**
|
||||
* \brief Macro to determine SDL version program was compiled against.
|
||||
|
||||
@@ -169,6 +169,24 @@ typedef enum
|
||||
SDL_WINDOWEVENT_HIT_TEST /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */
|
||||
} SDL_WindowEventID;
|
||||
|
||||
/**
|
||||
* \brief Event subtype for display events
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_DISPLAYEVENT_NONE, /**< Never used */
|
||||
SDL_DISPLAYEVENT_ORIENTATION /**< Display orientation has changed to data1 */
|
||||
} SDL_DisplayEventID;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */
|
||||
SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */
|
||||
SDL_ORIENTATION_LANDSCAPE_FLIPPED, /**< The display is in landscape mode, with the left side up, relative to portrait mode */
|
||||
SDL_ORIENTATION_PORTRAIT, /**< The display is in portrait mode */
|
||||
SDL_ORIENTATION_PORTRAIT_FLIPPED /**< The display is in portrait mode, upside down */
|
||||
} SDL_DisplayOrientation;
|
||||
|
||||
/**
|
||||
* \brief An opaque handle to an OpenGL context.
|
||||
*/
|
||||
@@ -316,18 +334,6 @@ extern DECLSPEC const char * SDLCALL SDL_GetDisplayName(int displayIndex);
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect);
|
||||
|
||||
/**
|
||||
* \brief Get the dots/pixels-per-inch for a display
|
||||
*
|
||||
* \note Diagonal, horizontal and vertical DPI can all be optionally
|
||||
* returned if the parameter is non-NULL.
|
||||
*
|
||||
* \return 0 on success, or -1 if no DPI information is available or the index is out of range.
|
||||
*
|
||||
* \sa SDL_GetNumVideoDisplays()
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
|
||||
|
||||
/**
|
||||
* \brief Get the usable desktop area represented by a display, with the
|
||||
* primary display located at 0,0
|
||||
@@ -347,6 +353,27 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, fl
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect);
|
||||
|
||||
/**
|
||||
* \brief Get the dots/pixels-per-inch for a display
|
||||
*
|
||||
* \note Diagonal, horizontal and vertical DPI can all be optionally
|
||||
* returned if the parameter is non-NULL.
|
||||
*
|
||||
* \return 0 on success, or -1 if no DPI information is available or the index is out of range.
|
||||
*
|
||||
* \sa SDL_GetNumVideoDisplays()
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
|
||||
|
||||
/**
|
||||
* \brief Get the orientation of a display
|
||||
*
|
||||
* \return The orientation of the display, or SDL_ORIENTATION_UNKNOWN if it isn't available.
|
||||
*
|
||||
* \sa SDL_GetNumVideoDisplays()
|
||||
*/
|
||||
extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetDisplayOrientation(int displayIndex);
|
||||
|
||||
/**
|
||||
* \brief Returns the number of available display modes.
|
||||
*
|
||||
|
||||
@@ -135,11 +135,11 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
|
||||
* \brief Get the names of the Vulkan instance extensions needed to create
|
||||
* a surface with \c SDL_Vulkan_CreateSurface().
|
||||
*
|
||||
* \param [in] window Window for which the required Vulkan instance
|
||||
* \param [in] \c NULL or window Window for which the required Vulkan instance
|
||||
* extensions should be retrieved
|
||||
* \param [in,out] count pointer to an \c unsigned related to the number of
|
||||
* \param [in,out] pCount pointer to an \c unsigned related to the number of
|
||||
* required Vulkan instance extensions
|
||||
* \param [out] names \c NULL or a pointer to an array to be filled with the
|
||||
* \param [out] pNames \c NULL or a pointer to an array to be filled with the
|
||||
* required Vulkan instance extensions
|
||||
*
|
||||
* \return \c SDL_TRUE on success, \c SDL_FALSE on error.
|
||||
@@ -153,6 +153,10 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
|
||||
* is smaller than the number of required extensions, \c SDL_FALSE will be
|
||||
* returned instead of \c SDL_TRUE, to indicate that not all the required
|
||||
* extensions were returned.
|
||||
*
|
||||
* \note If \c window is not NULL, it will be checked against its creation
|
||||
* flags to ensure that the Vulkan flag is present. This parameter
|
||||
* will be removed in a future major release.
|
||||
*
|
||||
* \note The returned list of extensions will contain \c VK_KHR_surface
|
||||
* and zero or more platform specific extensions
|
||||
@@ -160,12 +164,13 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
|
||||
* \note The extension names queried here must be enabled when calling
|
||||
* VkCreateInstance, otherwise surface creation will fail.
|
||||
*
|
||||
* \note \c window should have been created with the \c SDL_WINDOW_VULKAN flag.
|
||||
* \note \c window should have been created with the \c SDL_WINDOW_VULKAN flag
|
||||
* or be \c NULL
|
||||
*
|
||||
* \code
|
||||
* unsigned int count;
|
||||
* // get count of required extensions
|
||||
* if(!SDL_Vulkan_GetInstanceExtensions(window, &count, NULL))
|
||||
* if(!SDL_Vulkan_GetInstanceExtensions(NULL, &count, NULL))
|
||||
* handle_error();
|
||||
*
|
||||
* static const char *const additionalExtensions[] =
|
||||
@@ -179,7 +184,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
|
||||
* handle_error();
|
||||
*
|
||||
* // get names of required extensions
|
||||
* if(!SDL_Vulkan_GetInstanceExtensions(window, &count, names))
|
||||
* if(!SDL_Vulkan_GetInstanceExtensions(NULL, &count, names))
|
||||
* handle_error();
|
||||
*
|
||||
* // copy additional extensions after required extensions
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Submodule moonlight-common-c/moonlight-common-c updated: 558ba488e8...396b02a94d
@@ -56,6 +56,7 @@ SOURCES += \
|
||||
$$COMMON_C_DIR/src/RtspConnection.c \
|
||||
$$COMMON_C_DIR/src/RtspParser.c \
|
||||
$$COMMON_C_DIR/src/SdpGenerator.c \
|
||||
$$COMMON_C_DIR/src/SimpleStun.c \
|
||||
$$COMMON_C_DIR/src/VideoDepacketizer.c \
|
||||
$$COMMON_C_DIR/src/VideoStream.c
|
||||
HEADERS += \
|
||||
@@ -67,7 +68,7 @@ INCLUDEPATH += \
|
||||
CONFIG += warn_off staticlib
|
||||
DEFINES += HAS_SOCKLEN_T
|
||||
|
||||
debug {
|
||||
CONFIG(debug, debug|release) {
|
||||
# Enable asserts on debug builds
|
||||
DEFINES += LC_DEBUG
|
||||
}
|
||||
|
||||
+7
-2
@@ -3,10 +3,15 @@ SUBDIRS = \
|
||||
moonlight-common-c \
|
||||
qmdnsengine \
|
||||
app \
|
||||
soundio
|
||||
soundio \
|
||||
h264bitstream
|
||||
|
||||
# Build the dependencies in parallel before the final app
|
||||
app.depends = qmdnsengine moonlight-common-c soundio
|
||||
app.depends = qmdnsengine moonlight-common-c soundio h264bitstream
|
||||
win32 {
|
||||
SUBDIRS += AntiHooking
|
||||
app.depends += AntiHooking
|
||||
}
|
||||
|
||||
# Support debug and release builds from command line for CI
|
||||
CONFIG += debug_and_release
|
||||
|
||||
@@ -43,10 +43,6 @@ echo Copying dylib dependencies
|
||||
mkdir $BUILD_FOLDER/app/Moonlight.app/Contents/lib
|
||||
cp $SOURCE_ROOT/libs/mac/lib/*.dylib $BUILD_FOLDER/app/Moonlight.app/Contents/lib/ || fail "Dylib copy failed!"
|
||||
|
||||
echo Copying frameworks dependencies
|
||||
mkdir $BUILD_FOLDER/app/Moonlight.app/Contents/Frameworks
|
||||
cp -R $SOURCE_ROOT/libs/mac/Frameworks/ $BUILD_FOLDER/app/Moonlight.app/Contents/Frameworks/ || fail "Framework copy failed!"
|
||||
|
||||
echo Creating app bundle
|
||||
EXTRA_ARGS=
|
||||
if [ "$BUILD_CONFIG" == "Debug" ]; then EXTRA_ARGS="$EXTRA_ARGS -use-debug-libs"; fi
|
||||
|
||||
@@ -92,6 +92,10 @@ echo Copying DLL dependencies
|
||||
copy %SOURCE_ROOT%\libs\windows\lib\%ARCH%\*.dll %DEPLOY_FOLDER%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
echo Copying AntiHooking.dll
|
||||
copy %BUILD_FOLDER%\AntiHooking\%BUILD_CONFIG%\AntiHooking.dll %DEPLOY_FOLDER%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
echo Copying GC mapping list
|
||||
copy %SOURCE_ROOT%\app\SDL_GameControllerDB\gamecontrollerdb.txt %DEPLOY_FOLDER%
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
@@ -110,10 +114,12 @@ if !ERRORLEVEL! NEQ 0 goto Error
|
||||
|
||||
if "%SIGN%"=="1" (
|
||||
echo Signing deployed binaries
|
||||
set FILES_TO_SIGN=
|
||||
for /r "%DEPLOY_FOLDER%" %%f in (*.dll *.exe) do (
|
||||
signtool %SIGNTOOL_PARAMS% %%f
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
set FILES_TO_SIGN=!FILES_TO_SIGN! %%f
|
||||
)
|
||||
signtool %SIGNTOOL_PARAMS% !FILES_TO_SIGN!
|
||||
if !ERRORLEVEL! NEQ 0 goto Error
|
||||
)
|
||||
|
||||
echo Building MSI
|
||||
|
||||
+1
-1
Submodule soundio/libsoundio updated: 2bb21ad417...5d6a7210fa
@@ -23,6 +23,11 @@ CONFIG += staticlib
|
||||
QMAKE_CFLAGS += /TP
|
||||
}
|
||||
|
||||
# Older GCC versions defaulted to GNU89
|
||||
*-g++ {
|
||||
QMAKE_CFLAGS += -std=gnu99
|
||||
}
|
||||
|
||||
# Disable warnings
|
||||
CONFIG += warn_off
|
||||
|
||||
@@ -39,6 +44,11 @@ unix:!macx {
|
||||
}
|
||||
}
|
||||
|
||||
CONFIG(release, debug|release) {
|
||||
# Disable asserts on release builds
|
||||
DEFINES += NDEBUG
|
||||
}
|
||||
|
||||
DEFINES += \
|
||||
SOUNDIO_STATIC_LIBRARY \
|
||||
SOUNDIO_VERSION_MAJOR=1 \
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
Name="$(var.FullName)"
|
||||
Language="1033"
|
||||
Version="!(bind.fileVersion.MoonlightExe)"
|
||||
Manufacturer="Moonlight Game Streaming Team"
|
||||
Manufacturer="Moonlight Game Streaming Project"
|
||||
UpgradeCode="5c09f94e-f809-4c6a-9b7b-597c99f041fe">
|
||||
|
||||
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<Bundle Name="Moonlight Game Streaming Client"
|
||||
Version="!(bind.PackageVersion.Moonlight)"
|
||||
Manufacturer="Moonlight Game Streaming Team"
|
||||
Manufacturer="Moonlight Game Streaming Project"
|
||||
UpgradeCode="466fa35d-4be4-40ef-9ce5-afadc3b63bc5"
|
||||
HelpUrl="https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide"
|
||||
UpdateUrl="https://github.com/moonlight-stream/moonlight-qt/releases"
|
||||
|
||||
Reference in New Issue
Block a user