SDL 2 Cannot Open Controller but Joystick Recognized - c++

I am writing a C++ program using SDL 2 for the platform layer and opengl for graphics and rendering. I have a full working prototype with keyboard and mouse input. Now I am now trying to use SDL's game controller API to connect a gamepad (to replace or supplement keyboard controls). Unfortunately the controller does not seem to be recognized despite the fact that it works perfectly with other software. It's a Sony Dualshock 4 (for the Playstation 4 system). My system is Mac OS 10.9.5, and I am using SDL 2.0.5 with the official community controller database for SDL 2.0.5, which contains ps4 controller mappings:
030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X
I also added a new mapping using one of the official tools. That also loads successfully according to the relevant function call.
The following is my code, and it's about as close to a minimal example as I can get:
// in main
// window and graphics context initialization here
// initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) < 0) {
fprintf(stderr, "%s\n", "SDL could not initialize");
return EXIT_FAILURE;
}
// load controller mappings, I tested this and 35 mappings load successfully, which is expected
SDL_GameControllerAddMappingsFromFile("./mapping/gamecontrollerdb_205.txt");
// the controller handle
SDL_GameController* controller = nullptr;
// max_joysticks is 1, which means that the device connects at least
int max_joysticks = SDL_NumJoysticks();
if (max_joysticks < 1) {
return EXIT_FAILURE;
}
// this returns, which means that the joystick exists, but it isn't recognized as a game controller.
if (!SDL_IsGameController(0)) {
return EXIT_FAILURE;
}
// I never get passed this.
controller = SDL_GameControllerOpen(0);
fprintf(stdout, "CONTROLLER: %s\n", SDL_GameControllerName(controller));
Has anyone encountered this problem? I've done some preliminary searching as I mentioned, but it seems that usually either the number of joysticks is 0, or everything is recognized.
Also, SDL_CONTROLLERDEVICEADDED isn't firing when I connect the controller.
The controller is connected via USB before I start the program. Also, this is one of the new controllers, and I'm not sure whether the mappings work with that new one. I assume so considering that there are two distinct entries.
Thank you.
EDIT:
I double checked and the PS4 controller works fine as a joystick, but it isn't recognized as a controller, which means that the mapping is incorrect or non-existent. This may be because my controller is "version 2" of the dualshock 4, and I'm not sure whether a 2.0.5-compatible mapping was added. hmmm

The controller was recognized as a joystick but not as a controller, meaning that none of the available mappings I could find (in 2.0.5 controller mapping format) corresponded with the controller. Updating from SDL 2.0.5 to 2.0.8 also updated available mappings it seems, and now the controller is recognized as a game controller.
Note: normally it is a terrible idea to upgrade tools mid-project, but in this case it was safe to do.

Related

Can't go fullscreen under DirectX12

I have an app which uses DirectX12. I wanted to support fullscreen mode in my app.
However, each time I called IDXGISwapChain::SetFullscreenState(), I got this error:
DXGI ERROR: IDXGISwapChain::GetContainingOutput: The swapchain's adapter
does not control the output on which the swapchain's window resides.
The error code returned by IDXGISwapChain::SetFullscreenState() was
0x887a0004
My computer has two GPU:
Intel(R) HD Graphics 630 and
NVIDIA GeForce GTX 1060
the latter was the adapter used to create d3d12 device when the error occurred.
And if the adapter was the former, there would be no error.
The code flow used to create a IDXGISwapChain3 was
//variables used in the code example
ID3D12Device *pDevice;
IDXGIFactory4 *pDXGIFactory;
IDXGIAdapter *pAdapter;
ID3D12CommandQueue *pCommandQueue;
IDXGISwapChain1 *pTempSwapchain;
IDXGISwapChain3 *pSwapchain;
//the code flow
CreateDXGIFactory2();
pDXGIFactory->EnumAdapter();
D3D12CreateDevice(pAdapter, ...);
pD3DDevice->CreateCommandQueue();
pDXGIFactory->CreateSwapChainForHwnd(pCommandQueue, ..., &pTempSwapchain);
pTempSwapchain->QueryInterface(IID_PPV_ARGS(&pSwapChain));
The IDXGISwapChain::SetFullscreenState() should succeed, but it failed.
Note that the problem is a specific combination of a quirk of the DXGI debug layer and the way that the "hybrid graphics" solutions are implemented depending on which device you are using at the time.
The best option here is to just suppress the error:
#if defined(_DEBUG)
// Enable the debug layer (requires the Graphics Tools "optional feature").
//
// NOTE: Enabling the debug layer after device creation will invalidate the active device.
{
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf()))))
{
debugController->EnableDebugLayer();
}
else
{
OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n");
}
ComPtr<IDXGIInfoQueue> dxgiInfoQueue;
if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(dxgiInfoQueue.GetAddressOf()))))
{
dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true);
dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true);
DXGI_INFO_QUEUE_MESSAGE_ID hide[] =
{
80 /* IDXGISwapChain::GetContainingOutput: The swapchain's adapter does not control the output on which the swapchain's window resides. */,
};
DXGI_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumIDs = _countof(hide);
filter.DenyList.pIDList = hide;
dxgiInfoQueue->AddStorageFilterEntries(DXGI_DEBUG_DXGI, &filter);
}
}
#endif
I use this in all my templates on GitHub.
I have found a solution. Use IDXGIFactory6::EnumAdapterByGpuPreference() method instead of IDXGIFactory::EnumAdapter() method then the error will disappear.

Problem with Keypress simulation on Linux (Ubuntu 18)

I'm making a hobby project that is basically a bot for a very old flash game, the mouse move and click works fine, but all key presses make the operating system lag/stutter and sometimes stop listening to all keyboard inputs, real or fake.
I started using just XLib with XTests but didn't work, so I tried XSendEvent instead of XTests, but all symptoms stayed the same, so the last attempt was with XDO, which gave better results, but still freezes the OS.
this is the current snippet that I'm trying to use to simulate a keypress:
//Constructor
CheatCore::CheatCore() {
xdo_t x = xdo_new(NULL);
Window *list;
xdo_search_t search;
unsigned int nwindows;
memset(&search, 0, sizeof(xdo_search_t));
search.max_depth = -1;
search.require = xdo_search::SEARCH_ANY;
search.searchmask = SEARCH_CLASS | SEARCH_ONLYVISIBLE;
search.winclass = "Chrome";
int id = xdo_search_windows(x, &search, &list, &nwindows);
qDebug() << nwindows;
if(!nwindows){
qDebug() << "Chrome not found";
return;
}
w = list[0];
//I have to call activate twice to really bring it forward, I suspect that its
//because I use a transparent "overlay" that show stats for the cheat and it is set as Aways on top
//(i used Qt to set it to not get any Events)
xdo_activate_window(x,w);
xdo_activate_window(x,w);
}
//there is a function that executes every second to check if a pixel color has changed,
//if so, then the SendKey is called to Reload weapon magazine pressing the "space" key
void CheatCore::SendKey(){
xdo_activate_window(x,w);
xdo_activate_window(x,w);
xdo_send_keysequence_window(x, w, "space", 500);
}
I'm using a transparent overlay to show the bot status, with just some numbers appearing, it is a widget created using Qt that is AlwaysOnTop and the paint event draws the desired information's, it is another object and don't have direct impact in the CheatCore, but this is the window flags used to draw over a transparent window and ignore events.
setWindowFlags(Qt::WindowTransparentForInput | Qt::FramelessWindowHint |
Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
I didn't manage to understand what could be provoking this weird behavior, could it be the windowing system?
Also, I tried to find a Qt way of simulating mouse/keyboard inputs, but i didn't manage to find any solution to send events to other windows if there is a way possible of achieving this would be great!
The game i'm trying to automate is called "Storm the House"
If interested this is the link to the online repo : link
Can you help me make this work? Thank you!
Context about the setup:
Ubuntu 18.10 using VGA and Nvidia drivers (if it may influence the xserver)
Did you ever try to use xdotool from command line. To use xdotool you need to install package first.
To simualte a key press, you can use.
xdotool key <key>
For example if you want to simulate key press for X you can use this code
xdotool key x
Or any other combination like
xdotool key ctrl+f
Also you can replace key press with another one, for example if you want to replace pressing D with Backspace you can try this one
xdotool key D BackSpace
You can read complete guid online, also you can write script with this tool and use it in many different situations.
Also you can use it for remote connection too.
I hope this helps you with your little problem.
Using evdev is a linux specific option.
It's a simpler solution as you just need to open the correct file and write to it.
Take a look at this similar question to see how to get started.

XInputGetState hangs

I'm trying to use XInput API for my game engine (I'm using DirectX11 and C++). I just want to test if a controller is found so I #included and call XInputGetState but I get a strange behavior:
XINPUT_STATE state;
ZeroMemory(&state, sizeof(XINPUT_STATE));
DWORD result;
for (DWORD i = 0; i < XUSER_MAX_COUNT; i++)
{
result = XInputGetState(i, &state);
if (result == ERROR_SUCCESS)
ErrorBox(L"found controller on port ");
}
if I connect a controller the program hangs and freezes, while if I disconnect the controller the game launches. If I step into the code with the debugger the result is that the controller is found and the message box is displayed.
Why?
EDIT the problem seems to be in the call to ErrorBox: this function just displays a Message Box using Win32 API.
There is a performance hit when you check for a controller that wasn't attached last time you called it because it has to enumerate device, open driver connects, etc. Therefore, you are recommended to round-robin calls to check for new controllers. If you get ERROR_DEVICE_NOT_CONNECTED back, you shouldn't call XInputGetState again for that slot for a little while. For an example of this, see GamePad class in the Directx Tool Ki and the ThrottleRetry function.
In other words, the loop you wrote before is not a good idea to call every frame unless there are XUSER_MAX_COUNT controllers actually connected.

Qt for iOS locks up when app is launched face up. (qiosscreen.mm assertion)

I'm migrating a Qt for iOS project to Qt 5.5. In iOS 5.1.1 at least, the app fails to start if you launch it with the device face up. An assertion displays an error in qiosscreen.mm at line 344. Here's the Qt source code function that is failing:
Qt::ScreenOrientation QIOSScreen::orientation() const
{
// Auxiliary screens are always the same orientation as their primary orientation
if (m_uiScreen != [UIScreen mainScreen])
return Qt::PrimaryOrientation;
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
// At startup, iOS will report an unknown orientation for the device, even
// if we've asked it to begin generating device orientation notifications.
// In this case we fall back to the status bar orientation, which reflects
// the orientation the application was started up in (which may not match
// the physical orientation of the device, but typically does unless the
// application has been locked to a subset of the available orientations).
if (deviceOrientation == UIDeviceOrientationUnknown)
deviceOrientation = UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation);
// If the device reports face up or face down orientations, we can't map
// them to Qt orientations, so we pretend we're in the same orientation
// as before.
if (deviceOrientation == UIDeviceOrientationFaceUp || deviceOrientation == UIDeviceOrientationFaceDown) {
Q_ASSERT(screen());
return screen()->orientation();
}
return toQtScreenOrientation(deviceOrientation);
}
It displays an assertion at
Q_ASSERT(screen());
screen() must be returning 0, so screen()->orientation() is attempting to deference a null pointer. That screen() function is defined in the parent class, QPlatformScreen:
QScreen *QPlatformScreen::screen() const
{
Q_D(const QPlatformScreen);
return d->screen;
}
The constructor for that class initializes d->screen to 0:
QPlatformScreen::QPlatformScreen()
: d_ptr(new QPlatformScreenPrivate)
{
Q_D(QPlatformScreen);
d->screen = 0;
}
From the comments, I infer that d->screen is set at some point when the orientation is portrait or landscape, and then they fall back to that when it becomes face up / down. Since it is starting as face up, there is no prior good value to fall back to.
Has anyone else encountered this, or have a solution? Btw, I am not building from qt source and do not want to, so changing their code is not a solution for me if I can possibly avoid that.
I found that this only seems to be occurring when I launch the app from XCode or QtCreator. If I launch the app on the device the way it normally runs, this bug seems to be averted.

Loading Nib and Displaying Window in Objective C++

I am trying to load a Nib from a C++ constructor with Objective C++. I have searched and found enough examples to get some code together but it doesn't display the window. Or any windows for that matter.
Here is an example of the contructor:
JokeSystem::JokeSystem() : fileSystem("/Library/Application Support/Jokes/")
{
try
{
randSystem = new RandSelect<std::string>
(fileSystem.getAllFileContents("%\n"));
}
catch (std::ifstream::failure)
{
NSWindowController * errorWindowControl = [[NSWindowController alloc]
initWithWindowNibName:#"ErrorWindow"];
[errorWindowControl showWindow: nil];
}
}
The purpose of the contructor is to load the contents of a directory into a string. What I am try to do is display the error window when the files fail to open.
ErrorWindow.nib has a single window with an OK button and a NSTextView for the error, I set up a NSWindowController in the nib and connected it to the window.
My only link has been that most examples show this [errorWindowControl showWindow: self];
rather than showWindow: nil but because this is a C++ constructor I it doesn't have self and this doesn't work.
If it matters this contructor is called from the awakeFromNib method of the MainMenu.nib's primary NSObject.
Thanks
A bit of an odd way to approach Cocoa. I would encourage you to step back, learn Objective-C and then write your application with an Objective-C based Cocoa UI layer on top of whatever backing store or model layer you have.
In any case, there isn't anything particularly wrong with that code (save for the odd design).
The first thing to check is the return value of -initWithWindowNibName:. Is errorWindowControl actually non-nil? If it is nil, then the NIB failed to load.
How are you writing the Cocoa application itself? Standard app bundle using Xcode, I hope?
Also, you shouldn't be hardcoding the path to /Library/Application Support/. Actually, your application shouldn't use that directory as the only storage location; many users won't have write access to that directory and won't be able to install your app without administrator access.