Skip to content

Commit 70c222d

Browse files
committed
joystick: Add axis and button mapping
Adds backend for mapping buttons and axes to actions in the joystick control driver. A new enum of possible actions is added, and some new methods for querying and changing the mappings is added. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
1 parent d3255ea commit 70c222d

File tree

2 files changed

+143
-11
lines changed

2 files changed

+143
-11
lines changed

src/ptz-controls.cpp

Lines changed: 109 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@
2525
#include "settings.hpp"
2626
#include "ptz.h"
2727

28+
QStringList ptz_joy_action_names = {
29+
"None",
30+
"Pan",
31+
"Tilt",
32+
"Zoom",
33+
"Previous Camera",
34+
"Next Camera",
35+
"Previous Preset",
36+
"Next Preset",
37+
"Recall Preset"
38+
};
39+
2840
void ptz_load_controls(void)
2941
{
3042
const auto main_window = static_cast<QMainWindow *>(obs_frontend_get_main_window());
@@ -324,10 +336,11 @@ void PTZControls::joystickAxesChanged(const QJoystickDevice *jd, uint32_t update
324336
{
325337
if (isLocked() || !m_joystick_enable || !jd || jd->id != m_joystick_id)
326338
return;
327-
if (updated & 0b0011)
328-
setPanTilt(readAxis(jd, 0), -readAxis(jd, 1));
329-
if (updated & 0b1000)
330-
setZoom(-readAxis(jd, 3));
339+
int panTiltMask = (1 << joystick_pan_axis) | (1 << joystick_tilt_axis);
340+
if (updated & panTiltMask)
341+
setPanTilt(readAxis(jd, joystick_pan_axis), -readAxis(jd, joystick_tilt_axis));
342+
if (updated & (1 << joystick_zoom_axis))
343+
setZoom(-readAxis(jd, joystick_zoom_axis));
331344
}
332345

333346
void PTZControls::joystickAxisEvent(const QJoystickAxisEvent evt)
@@ -356,22 +369,68 @@ void PTZControls::joystickButtonEvent(const QJoystickButtonEvent evt)
356369
return;
357370
if (!evt.pressed)
358371
return;
359-
switch (evt.button) {
360-
case 0: /* A button; activate preset */
372+
switch (joystick_button_actions[evt.button]) {
373+
case PTZ_JOY_ACTION_CAMERA_PREV:
374+
ui->cameraList->cursorUp();
375+
break;
376+
case PTZ_JOY_ACTION_CAMERA_NEXT:
377+
ui->cameraList->cursorDown();
378+
break;
379+
case PTZ_JOY_ACTION_PRESET_PREV:
380+
ui->presetListView->cursorUp();
381+
break;
382+
case PTZ_JOY_ACTION_PRESET_NEXT:
383+
ui->presetListView->cursorDown();
384+
break;
385+
case PTZ_JOY_ACTION_PRESET_RECALL:
361386
index = ui->presetListView->currentIndex();
362387
if (index.isValid() && !isLocked())
363388
ui->presetListView->activated(index);
364389
break;
365-
case 4: /* left shoulder; previous camera */
366-
ui->cameraList->cursorUp();
367-
break;
368-
case 5: /* right shoulder; next camera */
369-
ui->cameraList->cursorDown();
390+
default:
370391
break;
371392
}
372393
}
373394
#endif /* ENABLE_JOYSTICK */
374395

396+
void PTZControls::setJoystickAxisAction(size_t axis, ptz_joy_action_id action)
397+
{
398+
if (joystick_axis_actions[axis] == action)
399+
return;
400+
joystick_axis_actions[axis] = action;
401+
402+
// Clear if this is an axis already used
403+
if (joystick_pan_axis == (int)axis)
404+
joystick_pan_axis = -1;
405+
if (joystick_tilt_axis == (int)axis)
406+
joystick_tilt_axis = -1;
407+
if (joystick_zoom_axis == (int)axis)
408+
joystick_zoom_axis = -1;
409+
410+
int old_axis = -1;
411+
if (action == PTZ_JOY_ACTION_PAN && joystick_pan_axis != (int)axis) {
412+
old_axis = joystick_pan_axis;
413+
joystick_pan_axis = (int)axis;
414+
} else if (action == PTZ_JOY_ACTION_TILT && joystick_tilt_axis != (int)axis) {
415+
old_axis = joystick_tilt_axis;
416+
joystick_tilt_axis = (int)axis;
417+
} else if (action == PTZ_JOY_ACTION_ZOOM && joystick_zoom_axis != (int)axis) {
418+
old_axis = joystick_zoom_axis;
419+
joystick_zoom_axis = (int)axis;
420+
}
421+
if (old_axis != -1)
422+
emit joystickAxisActionChanged(old_axis, PTZ_JOY_ACTION_NONE);
423+
emit joystickAxisActionChanged(axis, action);
424+
}
425+
426+
void PTZControls::setJoystickButtonAction(size_t button, ptz_joy_action_id action)
427+
{
428+
if (joystick_button_actions[button] == action)
429+
return;
430+
joystick_button_actions[button] = action;
431+
emit joystickButtonActionChanged(button, action);
432+
}
433+
375434
void PTZControls::copyActionsDynamicProperties()
376435
{
377436
// Themes need the QAction dynamic properties
@@ -405,6 +464,29 @@ void PTZControls::SaveConfig()
405464
obs_data_set_int(savedata, "joystick_id", m_joystick_id);
406465
obs_data_set_double(savedata, "joystick_speed", m_joystick_speed);
407466
obs_data_set_double(savedata, "joystick_deadzone", m_joystick_deadzone);
467+
468+
OBSDataArrayAutoRelease axis_actions = obs_data_array_create();
469+
for (auto axis : joystick_axis_actions.keys()) {
470+
if (joystick_axis_actions[axis] == PTZ_JOY_ACTION_NONE)
471+
continue;
472+
OBSDataAutoRelease d = obs_data_create();
473+
obs_data_set_int(d, "axis", axis);
474+
obs_data_set_int(d, "action", joystick_axis_actions[axis]);
475+
obs_data_array_push_back(axis_actions, d);
476+
}
477+
obs_data_set_array(savedata, "joystick_axis_actions", axis_actions);
478+
479+
OBSDataArrayAutoRelease button_actions = obs_data_array_create();
480+
for (auto button : joystick_button_actions.keys()) {
481+
if (joystick_button_actions[button] == PTZ_JOY_ACTION_NONE)
482+
continue;
483+
OBSDataAutoRelease d = obs_data_create();
484+
obs_data_set_int(d, "button", button);
485+
obs_data_set_int(d, "action", joystick_button_actions[button]);
486+
obs_data_array_push_back(button_actions, d);
487+
}
488+
obs_data_set_array(savedata, "joystick_button_actions", button_actions);
489+
408490
if (auto ptz = currCamera())
409491
obs_data_set_int(savedata, "current_selected", ptz->getId());
410492

@@ -460,6 +542,22 @@ void PTZControls::LoadConfig()
460542
m_joystick_speed = obs_data_get_double(loaddata, "joystick_speed");
461543
m_joystick_deadzone = obs_data_get_double(loaddata, "joystick_deadzone");
462544

545+
OBSDataArrayAutoRelease axis_actions = obs_data_get_array(loaddata, "joystick_axis_actions");
546+
for (size_t i = 0; i < obs_data_array_count(axis_actions); i++) {
547+
OBSDataAutoRelease d = obs_data_array_item(axis_actions, i);
548+
auto axis = obs_data_get_int(d, "axis");
549+
auto action = obs_data_get_int(d, "action");
550+
setJoystickAxisAction(axis, action);
551+
}
552+
553+
OBSDataArrayAutoRelease button_actions = obs_data_get_array(loaddata, "joystick_button_actions");
554+
for (size_t i = 0; i < obs_data_array_count(button_actions); i++) {
555+
OBSDataAutoRelease d = obs_data_array_item(button_actions, i);
556+
auto button = obs_data_get_int(d, "button");
557+
auto action = obs_data_get_int(d, "action");
558+
setJoystickButtonAction(button, action);
559+
}
560+
463561
const char *splitterStateStr = obs_data_get_string(loaddata, "splitter_state");
464562
if (splitterStateStr) {
465563
QByteArray splitterState = QByteArray::fromBase64(QByteArray(splitterStateStr));

src/ptz-controls.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@
1818
#include "ptz-device.hpp"
1919
#include "ui_ptz-controls.h"
2020

21+
typedef size_t ptz_joy_action_id;
22+
enum ptz_joy_action {
23+
PTZ_JOY_ACTION_NONE = 0,
24+
PTZ_JOY_ACTION_PAN,
25+
PTZ_JOY_ACTION_TILT,
26+
PTZ_JOY_ACTION_ZOOM,
27+
PTZ_JOY_ACTION_CAMERA_PREV,
28+
PTZ_JOY_ACTION_CAMERA_NEXT,
29+
PTZ_JOY_ACTION_PRESET_PREV,
30+
PTZ_JOY_ACTION_PRESET_NEXT,
31+
PTZ_JOY_ACTION_PRESET_RECALL,
32+
PTZ_JOY_ACTION_LAST_VALUE
33+
};
34+
typedef enum ptz_joy_action ptz_joy_action_t;
35+
extern QStringList ptz_joy_action_names;
36+
2137
class PTZControls : public QWidget {
2238
Q_OBJECT
2339

@@ -125,6 +141,20 @@ private slots:
125141
int m_joystick_id = -1;
126142
double m_joystick_deadzone = 0.0;
127143
double m_joystick_speed = 1.0;
144+
int joystick_pan_axis = -1;
145+
int joystick_tilt_axis = -1;
146+
int joystick_zoom_axis = -1;
147+
QMap<size_t, ptz_joy_action_id> joystick_axis_actions;
148+
QMap<size_t, ptz_joy_action_id> joystick_button_actions;
149+
150+
public slots:
151+
void setJoystickAxisAction(size_t axis, ptz_joy_action_id);
152+
void setJoystickButtonAction(size_t button, ptz_joy_action_id);
153+
154+
signals:
155+
void joystickAxisActionChanged(size_t axis, ptz_joy_action_id action);
156+
void joystickButtonActionChanged(size_t button, ptz_joy_action_id action);
157+
128158
#if defined(ENABLE_JOYSTICK)
129159
public:
130160
void joystickSetup();
@@ -137,12 +167,16 @@ private slots:
137167
int joystickId() { return m_joystick_id; };
138168
void setJoystickId(int id) { m_joystick_id = id; };
139169
double readAxis(const QJoystickDevice *jd, int axis);
170+
ptz_joy_action_id joystickAxisAction(size_t axis) { return joystick_axis_actions[axis]; };
171+
ptz_joy_action_id joystickButtonAction(size_t button) { return joystick_button_actions[button]; };
172+
140173
protected slots:
141174
void joystickAxesChanged(const QJoystickDevice *jd, uint32_t updated);
142175
void joystickAxisEvent(const QJoystickAxisEvent evt);
143176
void joystickButtonEvent(const QJoystickButtonEvent evt);
144177
void joystickPOVEvent(const QJoystickPOVEvent evt);
145178
#else
179+
public:
146180
void joystickSetup(){};
147181
#endif /* ENABLE_JOYSTICK */
148182

0 commit comments

Comments
 (0)