Skip to content

Commit 477fbc1

Browse files
committed
Added dock to change profile and listening on/off
1 parent 4e00799 commit 477fbc1

10 files changed

Lines changed: 294 additions & 12 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,12 @@ target_sources(
103103
src/joypad-input.cpp
104104
src/joypad-actions.cpp
105105
src/joypad-ui.cpp
106+
src/joypad-dock.cpp
106107
src/joypad-config.h
107108
src/joypad-input.h
108109
src/joypad-actions.h
109110
src/joypad-ui.h
111+
src/joypad-dock.h
110112
)
111113

112114
if(WIN32)

README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This plugin **does not** provide a visual overlay for your controller. Its purpo
2222
* **Auto de-duplication:** When both APIs expose the same physical controller, the plugin avoids duplicate entries/actions.
2323
* **Custom Hardware:** Compatible with **Arduino-based devices** that appear as a standard joystick, allowing you to use potentiometers, encoders, and sliders to control OBS.
2424
* **Intuitive UI:** A dedicated "Tools" menu dialog to create, edit, and manage all your bindings.
25+
* **Dedicated OBS Dock:** A compact dock panel with quick profile switching and gamepad listening on/off status/control.
2526
* **"Learn" Mode:** Simply press a button or move an axis on your controller to assign it to an action.
2627
* **Advanced Axis Configuration:** Calibrate axis range (Min/Max), set deadzones (Threshold), and invert axis direction for precise control.
2728
* **OBS Hotkey to Pause/Resume Controller Listening:** Toggle all gamepad input processing on/off from OBS Hotkeys.
@@ -60,6 +61,16 @@ Joypad to OBS supports a comprehensive set of commands to manage your stream:
6061
* **Toggle Recording:** Start/stop recording.
6162
* **Toggle Virtual Camera:** Start/stop virtual camera.
6263

64+
## Dock Panel
65+
66+
Joypad to OBS provides an OBS Dock for quick control without opening the full settings window.
67+
68+
* Open it from **View** -> **Docks** -> **Joypad to OBS**.
69+
* The dock shows the current Joypad profile in a dropdown.
70+
* Switching profile from the dock updates the active profile immediately.
71+
* The dock updates in real time when profile changes happen from hotkeys or other plugin UI.
72+
* The dock includes a listening status button (on/off icon) to enable or disable controller input processing.
73+
6374
## Profile Management
6475

6576
Joypad to OBS allows you to create and manage multiple profiles, each with its own set of bindings. This is useful for different games, scenes, or streaming setups.
@@ -102,15 +113,18 @@ If OSD notifications are enabled, this hotkey also shows the current listening s
102113
* **macOS:** `~/Library/Application Support/obs-studio/plugins/`
103114
* **Linux:** `~/.config/obs-studio/plugins/`
104115
2. **Open the configuration window:** In OBS, go to the **Tools** menu and select **Settings for Joypad to OBS**.
105-
3. **Select a Profile:** Choose the profile you want to edit from the dropdown menu, or create a new one.
106-
4. **Add a new binding:**
116+
3. **(Optional) Open the quick dock panel:** In OBS, go to **View** -> **Docks** -> **Joypad to OBS**.
117+
4. **Select a Profile:** Choose the profile you want to edit from the dropdown menu, or create a new one.
118+
* You can also switch the active profile directly from the dock dropdown.
119+
* Use the dock status icon to quickly enable/disable controller listening.
120+
5. **Add a new binding:**
107121
* Click the **"Add Command"** button.
108122
* Click **"Listen"** and press the button or move the axis on your controller that you want to use.
109123
* Select the **Action** you want to perform (e.g., "Switch Scene", "Set Source Mute").
110124
* Configure the target (e.g., choose the specific scene or source).
111125
* Click **OK** to save the binding.
112-
5. Your controller is now ready to control OBS!
113-
6. (Optional) In **OBS Settings -> Hotkeys**, assign `Joypad to OBS: Toggle gamepad listening` to quickly pause/resume controller input while streaming.
126+
6. Your controller is now ready to control OBS!
127+
7. (Optional) In **OBS Settings -> Hotkeys**, assign `Joypad to OBS: Toggle gamepad listening` to quickly pause/resume controller input while streaming.
114128

115129
## Building from Source
116130

data/locale/en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
JoypadToOBS.MenuTitle="Settings for Joypad to OBS"
2+
JoypadToOBS.Dock.Title="Joypad to OBS"
3+
JoypadToOBS.Dock.ListeningButton="Gamepad Listening: %1"
24
JoypadToOBS.DialogTitle="Settings for Joypad to OBS"
35
JoypadToOBS.Dialog.Description="Configure joypad commands to control scenes, sources, filters, and audio. Add, edit, or remove commands below."
46
JoypadToOBS.Dialog.AddTitle="Add Joypad Command"

data/locale/pt-BR.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
JoypadToOBS.MenuTitle="Configurações do Joypad para OBS"
2+
JoypadToOBS.Dock.Title="Joypad para OBS"
3+
JoypadToOBS.Dock.ListeningButton="Escuta do Controle: %1"
24
JoypadToOBS.DialogTitle="Configurações do Joypad para OBS"
35
JoypadToOBS.Dialog.Description="Configure comandos do joypad para controlar cenas, fontes, filtros e áudio. Adicione, edite ou remova comandos abaixo."
46
JoypadToOBS.Dialog.AddTitle="Adicionar comando do Joypad"

data/locale/pt-PT.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
JoypadToOBS.MenuTitle="Configurações do Joypad para OBS"
2+
JoypadToOBS.Dock.Title="Joypad para OBS"
3+
JoypadToOBS.Dock.ListeningButton="Escuta do Comando: %1"
24
JoypadToOBS.DialogTitle="Configurações do Joypad para OBS"
35
JoypadToOBS.Dialog.Description="Configure comandos do joypad para controlar cenas, fontes, filtros e áudio. Adicione, edite ou remova comandos abaixo."
46
JoypadToOBS.Dialog.AddTitle="Adicionar comando do Joypad"

src/joypad-dock.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
Joypad to OBS
3+
Copyright (C) 2026 FabioZumbi12 <admin@areaz12server.net.br>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 2 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License along
16+
with this program. If not, see <https://www.gnu.org/licenses/>
17+
*/
18+
19+
#include "joypad-dock.h"
20+
#include "joypad-ui.h"
21+
22+
#include <obs-module.h>
23+
24+
#include <QComboBox>
25+
#include <QLabel>
26+
#include <QPushButton>
27+
#include <QSignalBlocker>
28+
#include <QSizePolicy>
29+
#include <QStyle>
30+
#include <QTimer>
31+
#include <QHBoxLayout>
32+
#include <QVBoxLayout>
33+
#include <QWidget>
34+
35+
namespace {
36+
inline QString L(const char *key)
37+
{
38+
return QString::fromUtf8(obs_module_text(key));
39+
}
40+
} // namespace
41+
42+
JoypadControlDock::JoypadControlDock(QWidget *parent, JoypadConfigStore *config) : QDockWidget(parent), config_(config)
43+
{
44+
setObjectName(QStringLiteral("joypad_to_obs_dock"));
45+
setWindowTitle(L("JoypadToOBS.Dock.Title"));
46+
47+
auto *content = new QWidget(this);
48+
auto *layout = new QVBoxLayout(content);
49+
layout->setContentsMargins(6, 6, 6, 6);
50+
layout->setSpacing(6);
51+
layout->setAlignment(Qt::AlignTop);
52+
53+
auto *profile_row = new QHBoxLayout();
54+
profile_row->setContentsMargins(0, 0, 0, 0);
55+
profile_row->setSpacing(6);
56+
profile_row->addWidget(new QLabel(L("JoypadToOBS.Profile.Name"), content), 0);
57+
58+
profile_combo_ = new QComboBox(content);
59+
profile_combo_->setMinimumContentsLength(12);
60+
profile_combo_->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
61+
profile_combo_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
62+
profile_row->addWidget(profile_combo_, 2);
63+
64+
input_toggle_button_ = new QPushButton(content);
65+
input_toggle_button_->setCheckable(true);
66+
input_toggle_button_->setText(QString());
67+
input_toggle_button_->setFixedWidth(34);
68+
input_toggle_button_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
69+
profile_row->addWidget(input_toggle_button_, 0);
70+
71+
layout->addLayout(profile_row);
72+
setWidget(content);
73+
74+
connect(profile_combo_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
75+
if (!config_) {
76+
return;
77+
}
78+
config_->SetCurrentProfile(index);
79+
RefreshState();
80+
});
81+
connect(input_toggle_button_, &QPushButton::toggled, this,
82+
[](bool enabled) { JoypadUiSetInputListeningEnabled(enabled); });
83+
84+
update_timer_ = new QTimer(this);
85+
connect(update_timer_, &QTimer::timeout, this, [this]() { RefreshState(); });
86+
update_timer_->start(200);
87+
88+
RefreshState();
89+
}
90+
91+
void JoypadControlDock::RefreshState()
92+
{
93+
RefreshProfiles();
94+
if (!input_toggle_button_) {
95+
return;
96+
}
97+
98+
const bool enabled = JoypadUiIsInputListeningEnabled();
99+
if (input_toggle_button_->isChecked() != enabled) {
100+
const QSignalBlocker blocker(input_toggle_button_);
101+
input_toggle_button_->setChecked(enabled);
102+
}
103+
const QString status = enabled ? L("JoypadToOBS.Common.On") : L("JoypadToOBS.Common.Off");
104+
const QStyle::StandardPixmap icon_type = enabled ? QStyle::SP_DialogApplyButton : QStyle::SP_DialogCancelButton;
105+
input_toggle_button_->setIcon(style()->standardIcon(icon_type));
106+
input_toggle_button_->setToolTip(L("JoypadToOBS.Dock.ListeningButton").arg(status));
107+
}
108+
109+
void JoypadControlDock::RefreshProfiles()
110+
{
111+
if (!config_ || !profile_combo_) {
112+
return;
113+
}
114+
115+
const auto names = config_->GetProfileNames();
116+
bool needs_rebuild = profile_combo_->count() != (int)names.size();
117+
if (!needs_rebuild) {
118+
for (int i = 0; i < profile_combo_->count(); ++i) {
119+
if (profile_combo_->itemData(i).toString() != QString::fromStdString(names[(size_t)i])) {
120+
needs_rebuild = true;
121+
break;
122+
}
123+
}
124+
}
125+
126+
if (needs_rebuild) {
127+
const QSignalBlocker blocker(profile_combo_);
128+
profile_combo_->clear();
129+
for (const auto &name : names) {
130+
const QString q_name = QString::fromStdString(name);
131+
profile_combo_->addItem(q_name, q_name);
132+
}
133+
}
134+
135+
const int current = config_->GetCurrentProfileIndex();
136+
if (current >= 0 && current < profile_combo_->count() && profile_combo_->currentIndex() != current) {
137+
const QSignalBlocker blocker(profile_combo_);
138+
profile_combo_->setCurrentIndex(current);
139+
}
140+
}

src/joypad-dock.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Joypad to OBS
3+
Copyright (C) 2026 FabioZumbi12 <admin@areaz12server.net.br>
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 2 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License along
16+
with this program. If not, see <https://www.gnu.org/licenses/>
17+
*/
18+
19+
#pragma once
20+
21+
#include "joypad-config.h"
22+
23+
#include <QDockWidget>
24+
25+
class QComboBox;
26+
class QPushButton;
27+
class QTimer;
28+
29+
class JoypadControlDock : public QDockWidget {
30+
public:
31+
JoypadControlDock(QWidget *parent, JoypadConfigStore *config);
32+
void RefreshState();
33+
34+
private:
35+
void RefreshProfiles();
36+
37+
JoypadConfigStore *config_ = nullptr;
38+
QComboBox *profile_combo_ = nullptr;
39+
QPushButton *input_toggle_button_ = nullptr;
40+
QTimer *update_timer_ = nullptr;
41+
};

0 commit comments

Comments
 (0)