Skip to content

Commit c64cb72

Browse files
nuess0rkblaschke
authored andcommitted
Adding game controller support
Using the SDL2 library to use gamecontrollers/joypads as user input method.
1 parent 080e48b commit c64cb72

File tree

4 files changed

+182
-2
lines changed

4 files changed

+182
-2
lines changed

Diff for: src/RenderLoop.cpp

+130
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ void RenderLoop::Run()
3333

3434
_projectMWrapper.DisplayInitialPreset();
3535

36+
_controller = _sdlRenderingWindow.FindController();
37+
3638
while (!_wantsToQuit)
3739
{
3840
limiter.TargetFPS(_projectMWrapper.TargetFPS());
@@ -52,6 +54,10 @@ void RenderLoop::Run()
5254
_projectMWrapper.UpdateRealFPS(limiter.FPS());
5355
}
5456

57+
//Close game controller
58+
SDL_GameControllerClose(_controller);
59+
_controller = nullptr;
60+
5561
notificationCenter.removeObserver(_quitNotificationObserver);
5662

5763
projectm_playlist_set_preset_switched_event_callback(_playlistHandle, nullptr, nullptr);
@@ -106,6 +112,26 @@ void RenderLoop::PollEvents()
106112

107113
break;
108114

115+
case SDL_CONTROLLERDEVICEADDED:
116+
ControllerAdd(event.cdevice.which);
117+
118+
break;
119+
120+
case SDL_CONTROLLERDEVICEREMOVED:
121+
ControllerRemove(event.cdevice.which);
122+
123+
break;
124+
125+
case SDL_CONTROLLERBUTTONDOWN:
126+
ControllerDownEvent(event);
127+
128+
break;
129+
130+
case SDL_CONTROLLERBUTTONUP:
131+
ControllerUpEvent(event);
132+
133+
break;
134+
109135
case SDL_DROPFILE: {
110136
char* droppedFilePath = event.drop.file;
111137

@@ -415,6 +441,110 @@ void RenderLoop::MouseUpEvent(const SDL_MouseButtonEvent& event)
415441
}
416442
}
417443

444+
void RenderLoop::ControllerAdd(const int id )
445+
{
446+
if (!_controller)
447+
{
448+
_controller = SDL_GameControllerOpen(id);
449+
}
450+
poco_debug(_logger, "Controller added!");
451+
}
452+
453+
void RenderLoop::ControllerRemove(const int id )
454+
{
455+
if (_controller && id == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(_controller)))
456+
{
457+
SDL_GameControllerClose(_controller);
458+
_controller = _sdlRenderingWindow.FindController();
459+
}
460+
poco_debug(_logger, "Controller removed!");
461+
}
462+
463+
void RenderLoop::ControllerDownEvent(const SDL_Event& event)
464+
{
465+
if (!_controller || event.cdevice.which != SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(_controller)))
466+
{
467+
poco_debug(_logger, "No controller initialized");
468+
return;
469+
}
470+
471+
switch (event.cbutton.button)
472+
{
473+
case SDL_CONTROLLER_BUTTON_A:
474+
_sdlRenderingWindow.ToggleFullscreen();
475+
poco_debug(_logger, "A pressed!");
476+
break;
477+
478+
case SDL_CONTROLLER_BUTTON_B:
479+
Poco::NotificationCenter::defaultCenter().postNotification(new PlaybackControlNotification(PlaybackControlNotification::Action::RandomPreset, _keyStates._shiftPressed));
480+
poco_debug(_logger, "B pressed!");
481+
break;
482+
483+
case SDL_CONTROLLER_BUTTON_X:
484+
Poco::NotificationCenter::defaultCenter().postNotification(new PlaybackControlNotification(PlaybackControlNotification::Action::TogglePresetLocked));
485+
poco_debug(_logger, "X pressed!");
486+
break;
487+
488+
case SDL_CONTROLLER_BUTTON_Y:
489+
Poco::NotificationCenter::defaultCenter().postNotification(new PlaybackControlNotification(PlaybackControlNotification::Action::ToggleShuffle));
490+
poco_debug(_logger, "Y pressed!");
491+
break;
492+
493+
case SDL_CONTROLLER_BUTTON_BACK:
494+
_wantsToQuit = true;
495+
poco_debug(_logger, "Back pressed!");
496+
break;
497+
498+
case SDL_CONTROLLER_BUTTON_GUIDE:
499+
Poco::NotificationCenter::defaultCenter().postNotification(new PlaybackControlNotification(PlaybackControlNotification::Action::LastPreset, _keyStates._shiftPressed));
500+
poco_debug(_logger, "Guide pressed!");
501+
break;
502+
503+
case SDL_CONTROLLER_BUTTON_START:
504+
_projectMGui.Toggle();
505+
_sdlRenderingWindow.ShowCursor(_projectMGui.Visible());
506+
poco_debug(_logger, "Start pressed!");
507+
break;
508+
509+
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
510+
_audioCapture.NextAudioDevice();
511+
poco_debug(_logger, "Shoulder left pressed!");
512+
break;
513+
514+
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
515+
_sdlRenderingWindow.NextDisplay();
516+
poco_debug(_logger, "Shoulder right pressed!");
517+
break;
518+
519+
case SDL_CONTROLLER_BUTTON_DPAD_UP:
520+
// Increase beat sensitivity
521+
_projectMWrapper.ChangeBeatSensitivity(0.05f);
522+
poco_debug(_logger, "DPad up pressed!");
523+
break;
524+
525+
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
526+
// Decrease beat sensitivity
527+
_projectMWrapper.ChangeBeatSensitivity(-0.05f);
528+
poco_debug(_logger, "DPad down pressed!");
529+
break;
530+
531+
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
532+
Poco::NotificationCenter::defaultCenter().postNotification(new PlaybackControlNotification(PlaybackControlNotification::Action::PreviousPreset, _keyStates._shiftPressed));
533+
poco_debug(_logger, "DPad left pressed!");
534+
break;
535+
536+
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
537+
Poco::NotificationCenter::defaultCenter().postNotification(new PlaybackControlNotification(PlaybackControlNotification::Action::NextPreset, _keyStates._shiftPressed));
538+
poco_debug(_logger, "DPad right pressed!");
539+
break;
540+
}
541+
}
542+
543+
void RenderLoop::ControllerUpEvent(const SDL_Event& event)
544+
{
545+
546+
}
547+
418548
void RenderLoop::QuitNotificationHandler(const Poco::AutoPtr<QuitNotification>& notification)
419549
{
420550
_wantsToQuit = true;

Diff for: src/RenderLoop.h

+26
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,30 @@ class RenderLoop
6161
*/
6262
void MouseUpEvent(const SDL_MouseButtonEvent& event);
6363

64+
/**
65+
* @brief Handles SDL game controller add events (plugin in a new controller) events.
66+
* @param id The added controller id
67+
*/
68+
void ControllerAdd( int id );
69+
70+
/**
71+
* @brief Handles SDL game controller remove events.
72+
* @param id The removed controller id
73+
*/
74+
void ControllerRemove( int id );
75+
76+
/**
77+
* @brief Handles SDL game controller button down events.
78+
* @param event The controller button event
79+
*/
80+
void ControllerDownEvent(const SDL_Event& event);
81+
82+
/**
83+
* @brief Handles SDL game controller button up events.
84+
* @param event The controller button event
85+
*/
86+
void ControllerUpEvent(const SDL_Event& event);
87+
6488
/**
6589
* @brief Handler for quit notifications.
6690
* @param notification The received notification.
@@ -90,4 +114,6 @@ class RenderLoop
90114
Poco::AutoPtr<Poco::Util::AbstractConfiguration> _userConfig; //!< View of the "projectM" configuration subkey in the "user" configuration.
91115

92116
Poco::Logger& _logger{Poco::Logger::get("RenderLoop")}; //!< The class logger.
117+
118+
SDL_GameController *_controller;
93119
};

Diff for: src/SDLRenderingWindow.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ void SDLRenderingWindow::NextDisplay()
196196

197197
void SDLRenderingWindow::CreateSDLWindow()
198198
{
199-
SDL_InitSubSystem(SDL_INIT_VIDEO);
199+
SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
200200

201201
int width{_config->getInt("width", 800)};
202202
int height{_config->getInt("height", 600)};
@@ -307,7 +307,7 @@ void SDLRenderingWindow::DestroySDLWindow()
307307
SDL_DestroyWindow(_renderingWindow);
308308
_renderingWindow = nullptr;
309309

310-
SDL_QuitSubSystem(SDL_INIT_VIDEO);
310+
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
311311
}
312312

313313
void SDLRenderingWindow::DumpOpenGLInfo()
@@ -461,3 +461,21 @@ void SDLRenderingWindow::OnConfigurationPropertyRemoved(const std::string& key)
461461
UpdateWindowTitle();
462462
}
463463
}
464+
465+
SDL_GameController* SDLRenderingWindow::FindController() {
466+
//Check for joysticks
467+
if( SDL_NumJoysticks() < 1 )
468+
{
469+
poco_debug(_logger, "No joysticks connected");
470+
}
471+
472+
//For simplicity, we’ll only be setting up and tracking a single
473+
//controller at a time
474+
for (int i = 0; i < SDL_NumJoysticks(); i++) {
475+
if (SDL_IsGameController(i)) {
476+
return SDL_GameControllerOpen(i);
477+
}
478+
}
479+
480+
return nullptr;
481+
}

Diff for: src/SDLRenderingWindow.h

+6
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ class SDLRenderingWindow : public Poco::Util::Subsystem
9696

9797
SDL_GLContext GetGlContext() const;
9898

99+
/**
100+
* @brief Returns the ID of the first game controller found
101+
* @return SDL_GameController * Returns a gamecontroller identifier or NULL
102+
*/
103+
SDL_GameController* FindController();
104+
99105
protected:
100106

101107
/**

0 commit comments

Comments
 (0)