Why does SDL_NumJoysticks() never update? - sdl

I was writing a small program in C that utilizes SDL 2.0, and ran into a problem when I couldn't get SDL_NumJoysticks() to report the number of joysticks plugged in at the time of the function call. I believe that it is reporting the number of joysticks connected during one of SDL's initialization functions (I would guess 'SDL_Init()', but I have no evidence), and then keeps on giving you that number throughout the rest of the program. Here is a short test program that I have been using:
#include <stdio.h>
#include <SDL2/SDL.h>
int main() {
SDL_Event event;
SDL_Window *window;
short joysticks = 0;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
fprintf(stderr, "SDL_Init error: %s\n", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("Test window", 0, 0, 800, 600, SDL_WINDOW_SHOWN);
if (window == NULL) {
fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError());
return 1;
}
printf("%s\n", SDL_GetError());
while (1) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
printf("%s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
} else if (event.type == SDL_JOYDEVICEADDED) {
printf("Joystick added!\n");
} else if (event.type == SDL_JOYDEVICEREMOVED) {
printf("Joystick removed!\n");
}
}
if (SDL_NumJoysticks() > joysticks) {
printf("Joystick inserted.\n");
joysticks++;
} else if (SDL_NumJoysticks() < joysticks && SDL_NumJoysticks() >= 0) {
printf("Joystick removed.\n");
joysticks--;
} else if (SDL_NumJoysticks() < 0) {
printf("Something went wrong!\n");
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
return 0;
}
The program accurately reports the number of joysticks plugged in when the program is started, but does absolutely nothing after that.
The official SDL docs for SDL_Numjoysticks() state that it "Returns the number of attached joysticks on success". How can I get it to tell me the number of joysticks plugged in at the time of the function call? Am I making a mistake in my code, or is that just not the way that SDL_NumJoysticks() works?

Make sure you follow these steps and see if you still have problems:
Call SDL_JoystickEventState(SDL_ENABLE) after SDL_INIT
If that is not enough, try to force an update by calling SDL_JoystickUpdate(); before while (SDL_PollEvent(&event))
EDIT: More info that I think should be useful:
Always call SDL_PollEvent on the Main Thread (Or SDL_PumpEvents() on Main Thread and SDL_PeepEvents elsewhere)
If you dont do that, SDL wont update the number of joysticks nor hotplug events
Other joystick events work when you pump outside the Main thread but it is not recommended.

Related

Empty SDL2 window taking lots (40%+) GPU to render?

I've been trying to learn how to use SDL2, and am trying to follow the tutorials here for that. From example 7 (texture loading / hardware rendering), I've put together this stripped down example. As far as I can tell, the code is only calling SDL_RenderClear() and SDL_RenderPresent() in the render loop, VSYNC'd to my monitor (100 Hz in this case). However, I'm seeing Windows report 40% GPU utilization when doing this, which seems high for doing nothing. My GPU sits at 1-2% utilization when the SDL2 program is not running.
Removing just the SDL_RenderPresent() call brings the usage all the way down to 1-2% again, but then nothing gets drawn, which makes me think that the issue is either in SDL2's rendering, or (much more likely), how I've configured it.
Is this high GPU utilization (when doing nothing) expected? Is there anything I can do to minimize the GPU utilization (while still using hardware rendering)?
===================================
Machine details:
Windows 10
Threadripper 3970x CPU (3.7 GHz 32 core)
256 GB RAM DDR4 3200 MHz
1x RTX 3090 GPU
3x 1440p 100Hz monitors
GPU utilization (shown via Task Manager and Xbox Game Bar):
Code:
#define SDL_MAIN_HANDLED
/*This source code copyrighted by Lazy Foo' Productions (2004-2020)
and may not be redistributed without written permission.*/
// Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <stdio.h>
#include <string>
// Screen dimension constants
const int SCREEN_WIDTH = 1920;
const int SCREEN_HEIGHT = 1080;
// Starts up SDL and creates window
bool init();
// Frees media and shuts down SDL
void close();
// The window we'll be rendering to
SDL_Window* gWindow = NULL;
// The window renderer
SDL_Renderer* gRenderer = NULL;
bool init() {
// Initialization flag
bool success = true;
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
} else {
// Create window
gWindow = SDL_CreateWindow(
"SDL Tutorial",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
if (gWindow == NULL) {
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
} else {
// Create renderer for window
gRenderer =
SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (gRenderer == NULL) {
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
} else {
// Initialize renderer color
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0x00, 0x00, 0x00);
}
}
}
return success;
}
void close() {
// Destroy window
SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow);
gWindow = NULL;
gRenderer = NULL;
// Quit SDL subsystems
SDL_Quit();
}
int main(int argc, char* args[]) {
// Start up SDL and create window
if (!init()) {
printf("Failed to initialize!\n");
} else {
// Main loop flag
bool quit = false;
// Event handler
SDL_Event e;
// While application is running
while (!quit) {
// Handle events on queue
while (SDL_PollEvent(&e) != 0) {
// User requests quit
if (e.type == SDL_QUIT) {
quit = true;
}
}
// Clear screen
SDL_RenderClear(gRenderer);
//Update screen
SDL_RenderPresent( gRenderer );
}
}
// Free resources and close SDL
close();
return 0;
}

c++ sdl window freeze and issues with sdl

SDL just pisses me off, please help.
I'm trying just to show a window, this is the code :
#include <iostream>
#define SDL_MAIN_HANDLED
#include "SDL.h"
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *window = SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 600, 480, SDL_WINDOW_SHOWN);
if (window == NULL)
return 1;
SDL_Event event;
bool running = true;
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
}
}
}
SDL_Quit();
std::cout << "Hello :)" << std::endl;
return 0;
}
Now, the issue is that it says that the program now responding and I have a "loading" icon for the mouse. Second issue is that I cannot use SDL_INIT_EVERYTHING for some reason, it just gets stuck and nothing outputs when I try to output after init.
I tried multiple sdl files x86 , x64.
I have windows 10 64bit OS.
I really start to lose my sanity here , please help.
EDIT :
the window works perfectly fine with SDL_INIT_EVERYTHING but it takes the computer to load everything for 1 minute and 50 seconds. which is a lot of time.
But when I only init SDL_INIT_VIDEO , it's not responding.
Any solution ?
Okay, so I have downloaded an older version 2.0.5 instead of the new "stable" version and seems like it works. I guess the new version just have bugs that needs to be fixed.

SDL_MOUSEBUTTONUP occurring even before releasing mouse button?

I'm trying to make a video player using SDL and ffmpeg in C++. I've created two separate threads, one that renders the video on the SDL window and one that handles window events. When the user clicks and releases on the video I want it to toggle playback/pause. However, it fires multiple times and the event occurs even before I release the mouse which results in unpredictable behavior.
My code:
SDL_Event event;
while (1)
{
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT:
SDL_DestroyWindow(screen);
SDL_Quit();
break;
case SDL_MOUSEBUTTONUP:
if (event.button.state == SDL_RELEASED)
{
printf("Mouse released\n");
}
break;
}
}
When I click the window and hold down I would expect it wouldn't print Mouse released until I release the button. However, it prints Mouse released the entire time I hold down the mouse button. I don't know if maybe this has to do with me using a touchpad on my laptop.
SDL_PollEvent has a return value, you are ignoring.
[It] returns 1 if there are any pending events, or 0 if there are none available.
Given your code logic, whenever there is no pending event, you keep handling the previous event over and over again, until a new event arrives. This leads to the observed behavior.
The easiest fix would be to wrap the entire event handling inside an if (SDL_PollEvent(&event)) { /* Event handling */ } conditional.
EDIT: My answer is wrong, check IInspectable's answer.
Your error is that you're not checking all the pending events given by pollEvent, just one. Try this code and tell me how many button ups you get.
#include <SDL2/SDL.h>
#include <iostream>
int main(int argc, char *argv[]) {
if(SDL_Init(SDL_INIT_VIDEO) != 0) {
throw std::runtime_error("SDL failed to initialize.\n");
}
SDL_Window *window = SDL_CreateWindow("App", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, NULL);
bool done = false;
while(!done) {
SDL_Event event;
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) {
done = true;
}
if (event.type == SDL_MOUSEBUTTONUP) {
if (event.button.state == SDL_RELEASED) {
printf("Mouse released\n");
}
}
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

SDL2 - Window cannot be reopened

I am writing a simple SDL2 application with 2 windows.
The first window (window variable) is shown when the application starts, the second one (window2 variable) is hidden.
Expected behavior:
I click on the first window, the second window pops up, then I close the second window.
And I can close and reopen the window as much as I want.
Observed behavior:
Once I close the second window, if I reclick in the first window, the second window doesn't appear as expected.
As stated in my comment: the window doesn't appear in my window manager (i.e. Wayland).
The code:
#include <SDL2/SDL.h>
int main()
{
SDL_Window* window, *window2 = NULL;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
return 1;
} else {
window = SDL_CreateWindow("ONE", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
window2 = SDL_CreateWindow("TWO", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_HIDDEN);
if (window == NULL || window2 == NULL) {
SDL_DestroyWindow(window);
SDL_DestroyWindow(window2);
return 1;
}
bool running = true;
while(running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_WINDOWEVENT) {
if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
if (SDL_GetWindowID(window) == event.window.windowID) {
running = false;
} else {
SDL_HideWindow(window2);
}
}
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
SDL_ShowWindow(window2);
}
}
}
}
SDL_DestroyWindow(window);
SDL_DestroyWindow(window2);
SDL_Quit();
return 0;
}
This is an SDL bug that may or may not have been fixed by this patch.
You should call SDL_RaiseWindow to place the second window on top of the other.
From lazyfoo's legendary SDL tutorials:
void LWindow::focus()
{
//Restore window if needed
if( !mShown )
SDL_ShowWindow( mWindow );
//Move window forward
SDL_RaiseWindow( mWindow );
}

Is there something wrong with my cleanup code? (OpenGL + SDL)

I think I have a bug in my program. I use SDL and OpenGL to render an animation. The program also measures the average FPS. Tipically, when I run the program, it will run at around 550 FPS.
However, if I start a second instance of the program, the FPS drops for both at around half (220 FPS). The strange thing is that if I close the first instance, the second one will still run at only 220 FPS. This leads me to believe that my cleanup code is somehow flawed.
Sometimes, even if I run a single instance, it will run at only 220 FPS, probably due to a previous instance that failed to clean up properly. Is there something wrong with my approach below?
I use a screen class which has the following *tors:
namespace gfx
{
screen::screen(const settings& vs) : dbl_buf_(false), sdl_surface_(0)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
throw util::exception(::std::string("Unable to initialize SDL video: ") + SDL_GetError());
if (!set(vs))
{
SDL_Quit();
throw util::exception("Unable to setup initial video mode.");
}
glewInit();
}
screen::~screen()
{
SDL_Quit();
}
bool screen::set(const settings& vs)
{
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Uint32 flags = SDL_HWSURFACE | SDL_OPENGL;
if (vs.full_screen) flags |= SDL_FULLSCREEN;
sdl_surface_ = SDL_SetVideoMode(vs.size_x, vs.size_y, vs.bpp, flags);
if (!sdl_surface_) return false;
settings_ = vs;
int db_flag = 0;
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &db_flag);
dbl_buf_ = (db_flag == 1);
return true;
}
// ...
}
Also:
int main()
{
try
{
gfx::settings vs = {800, 600, 32, false};
gfx::screen scr(vs);
// main app loop, render animation using OpenGL calls
// loop runs while running_ variable is true (see below)
}
// catch, etc.
return 0;
}
If it makes any difference, I use Linux and an ATI card.
Update: Event handling code:
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
running_ = false;
break;
case SDL_QUIT:
running_ = false;
break;
default:
world_.process_event(event);
break;
}
}
When a process terminates all the resources it used are freed automatically. That includes OpenGL. What may happen is, that you don't terminate your process but only hide the window by clicking the close button.