mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-09 06:26:26 -05:00
Add support for websocket messages not following the OBS WS protocol
This commit is contained in:
parent
dbb674aa8e
commit
b71f633fac
|
|
@ -952,6 +952,7 @@ AdvSceneSwitcher.connection.password="Password:"
|
|||
AdvSceneSwitcher.connection.reconnect="Reconnect automatically:"
|
||||
AdvSceneSwitcher.connection.reconnectDelay="Automatically reconnect after:"
|
||||
AdvSceneSwitcher.connection.connectOnStart="Connect on startup:"
|
||||
AdvSceneSwitcher.connection.useOBSWebsocketProtocol="<html><head/><body><p>Use the obs-websocket <a href=\"https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md\"><span style=\" text-decoration: underline; color:#268bd2;\">protocol</span></a></p></body></html>"
|
||||
AdvSceneSwitcher.connection.test="Test connection"
|
||||
AdvSceneSwitcher.connection.status.disconnected="Disconnected"
|
||||
AdvSceneSwitcher.connection.status.connecting="Connecting"
|
||||
|
|
|
|||
|
|
@ -46,14 +46,16 @@ void SwitcherData::LoadConnections(obs_data_t *obj)
|
|||
|
||||
Connection::Connection(std::string name, std::string address, uint64_t port,
|
||||
std::string pass, bool connectOnStart, bool reconnect,
|
||||
int reconnectDelay)
|
||||
int reconnectDelay, bool useOBSWebsocketProtocol)
|
||||
: Item(name),
|
||||
_address(address),
|
||||
_port(port),
|
||||
_password(pass),
|
||||
_connectOnStart(connectOnStart),
|
||||
_reconnect(reconnect),
|
||||
_reconnectDelay(reconnectDelay)
|
||||
_reconnectDelay(reconnectDelay),
|
||||
_useOBSWSProtocol(useOBSWebsocketProtocol),
|
||||
_client(useOBSWebsocketProtocol)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -66,6 +68,8 @@ Connection::Connection(const Connection &other) : Item(other)
|
|||
_connectOnStart = other._connectOnStart;
|
||||
_reconnect = other._reconnect;
|
||||
_reconnectDelay = other._reconnectDelay;
|
||||
_useOBSWSProtocol = other._useOBSWSProtocol;
|
||||
_client.UseOBSWebsocketProtocol(_useOBSWSProtocol);
|
||||
}
|
||||
|
||||
Connection &Connection::operator=(const Connection &other)
|
||||
|
|
@ -78,6 +82,8 @@ Connection &Connection::operator=(const Connection &other)
|
|||
_connectOnStart = other._connectOnStart;
|
||||
_reconnect = other._reconnect;
|
||||
_reconnectDelay = other._reconnectDelay;
|
||||
_client.UseOBSWebsocketProtocol(_useOBSWSProtocol);
|
||||
_useOBSWSProtocol = other._useOBSWSProtocol;
|
||||
_client.Disconnect();
|
||||
}
|
||||
return *this;
|
||||
|
|
@ -234,6 +240,7 @@ ConnectionSettingsDialog::ConnectionSettingsDialog(QWidget *parent,
|
|||
"AdvSceneSwitcher.connection.add", parent),
|
||||
_address(new QLineEdit()),
|
||||
_port(new QSpinBox()),
|
||||
_useOBSWSProtocol(new QCheckBox()),
|
||||
_password(new QLineEdit()),
|
||||
_showPassword(new QPushButton()),
|
||||
_connectOnStart(new QCheckBox()),
|
||||
|
|
@ -257,7 +264,10 @@ ConnectionSettingsDialog::ConnectionSettingsDialog(QWidget *parent,
|
|||
_connectOnStart->setChecked(settings._connectOnStart);
|
||||
_reconnect->setChecked(settings._reconnect);
|
||||
_reconnectDelay->setValue(settings._reconnectDelay);
|
||||
_useOBSWSProtocol->setChecked(settings._useOBSWSProtocol);
|
||||
|
||||
QWidget::connect(_useOBSWSProtocol, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(ProtocolChanged(int)));
|
||||
QWidget::connect(_reconnect, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(ReconnectChanged(int)));
|
||||
QWidget::connect(_showPassword, SIGNAL(pressed()), this,
|
||||
|
|
@ -312,6 +322,12 @@ ConnectionSettingsDialog::ConnectionSettingsDialog(QWidget *parent,
|
|||
row, 0);
|
||||
layout->addWidget(_reconnectDelay, row, 1);
|
||||
++row;
|
||||
layout->addWidget(
|
||||
new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.connection.useOBSWebsocketProtocol")),
|
||||
row, 0);
|
||||
layout->addWidget(_useOBSWSProtocol, row, 1);
|
||||
++row;
|
||||
layout->addWidget(_test, row, 0);
|
||||
layout->addWidget(_status, row, 1);
|
||||
++row;
|
||||
|
|
@ -319,9 +335,16 @@ ConnectionSettingsDialog::ConnectionSettingsDialog(QWidget *parent,
|
|||
setLayout(layout);
|
||||
|
||||
ReconnectChanged(_reconnect->isChecked());
|
||||
ProtocolChanged(_useOBSWSProtocol->isChecked());
|
||||
HidePassword();
|
||||
}
|
||||
|
||||
void ConnectionSettingsDialog::ProtocolChanged(int state)
|
||||
{
|
||||
_password->setEnabled(state);
|
||||
_showPassword->setEnabled(state);
|
||||
}
|
||||
|
||||
void ConnectionSettingsDialog::ReconnectChanged(int state)
|
||||
{
|
||||
_reconnectDelay->setEnabled(state);
|
||||
|
|
@ -365,6 +388,7 @@ void ConnectionSettingsDialog::HidePassword()
|
|||
|
||||
void ConnectionSettingsDialog::TestConnection()
|
||||
{
|
||||
_testConnection.UseOBSWebsocketProtocol(_useOBSWSProtocol->isChecked());
|
||||
_testConnection.Disconnect();
|
||||
_testConnection.Connect(GetUri(_address->text().toStdString(),
|
||||
_port->value()),
|
||||
|
|
@ -391,6 +415,7 @@ bool ConnectionSettingsDialog::AskForSettings(QWidget *parent,
|
|||
settings._connectOnStart = dialog._connectOnStart->isChecked();
|
||||
settings._reconnect = dialog._reconnect->isChecked();
|
||||
settings._reconnectDelay = dialog._reconnectDelay->value();
|
||||
settings.UseOBSWebsocketProtocol(dialog._useOBSWSProtocol->isChecked());
|
||||
settings.Reconnect();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -398,6 +423,16 @@ bool ConnectionSettingsDialog::AskForSettings(QWidget *parent,
|
|||
void Connection::Load(obs_data_t *obj)
|
||||
{
|
||||
Item::Load(obj);
|
||||
|
||||
if (obs_data_has_user_value(obj, "version")) {
|
||||
UseOBSWebsocketProtocol(
|
||||
obs_data_get_bool(obj, "useOBSWSProtocol"));
|
||||
} else {
|
||||
// TODO: Remove this fallback in future version
|
||||
_useOBSWSProtocol = true;
|
||||
}
|
||||
_client.UseOBSWebsocketProtocol(_useOBSWSProtocol);
|
||||
|
||||
_address = obs_data_get_string(obj, "address");
|
||||
_port = obs_data_get_int(obj, "port");
|
||||
_password = obs_data_get_string(obj, "password");
|
||||
|
|
@ -414,12 +449,20 @@ void Connection::Load(obs_data_t *obj)
|
|||
void Connection::Save(obs_data_t *obj) const
|
||||
{
|
||||
Item::Save(obj);
|
||||
obs_data_set_bool(obj, "useOBSWSProtocol", _useOBSWSProtocol);
|
||||
obs_data_set_string(obj, "address", _address.c_str());
|
||||
obs_data_set_int(obj, "port", _port);
|
||||
obs_data_set_string(obj, "password", _password.c_str());
|
||||
obs_data_set_bool(obj, "connectOnStart", _connectOnStart);
|
||||
obs_data_set_bool(obj, "reconnect", _reconnect);
|
||||
obs_data_set_int(obj, "reconnectDelay", _reconnectDelay);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
}
|
||||
|
||||
void Connection::UseOBSWebsocketProtocol(bool useOBSWSProtocol)
|
||||
{
|
||||
_useOBSWSProtocol = useOBSWSProtocol;
|
||||
_client.UseOBSWebsocketProtocol(useOBSWSProtocol);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Connection : public Item {
|
|||
public:
|
||||
Connection(std::string name, std::string address, uint64_t port,
|
||||
std::string pass, bool connectOnStart, bool reconnect,
|
||||
int reconnectDelay);
|
||||
int reconnectDelay, bool useOBSWebsocketProtocol);
|
||||
Connection() = default;
|
||||
Connection(const Connection &);
|
||||
Connection &operator=(const Connection &);
|
||||
|
|
@ -42,6 +42,9 @@ public:
|
|||
std::vector<std::string> &Events() { return _client.Events(); }
|
||||
|
||||
private:
|
||||
void UseOBSWebsocketProtocol(bool);
|
||||
|
||||
bool _useOBSWSProtocol = true;
|
||||
std::string _address = "localhost";
|
||||
uint64_t _port = 4455;
|
||||
std::string _password = "password";
|
||||
|
|
@ -70,6 +73,7 @@ public:
|
|||
static bool AskForSettings(QWidget *parent, Connection &settings);
|
||||
|
||||
private slots:
|
||||
void ProtocolChanged(int);
|
||||
void ReconnectChanged(int);
|
||||
void ShowPassword();
|
||||
void HidePassword();
|
||||
|
|
@ -79,6 +83,7 @@ private slots:
|
|||
private:
|
||||
QLineEdit *_address;
|
||||
QSpinBox *_port;
|
||||
QCheckBox *_useOBSWSProtocol;
|
||||
QLineEdit *_password;
|
||||
QPushButton *_showPassword;
|
||||
QCheckBox *_connectOnStart;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ extern "C" void RegisterWebsocketVendor()
|
|||
}
|
||||
}
|
||||
|
||||
WSConnection::WSConnection() : QObject(nullptr)
|
||||
WSConnection::WSConnection(bool useOBSProtocol)
|
||||
: QObject(nullptr), _useOBSProtocol(useOBSProtocol)
|
||||
{
|
||||
_client.get_alog().clear_channels(
|
||||
websocketpp::log::alevel::frame_header |
|
||||
|
|
@ -86,9 +87,7 @@ WSConnection::WSConnection() : QObject(nullptr)
|
|||
_client.set_reuse_addr(true);
|
||||
#endif
|
||||
|
||||
_client.set_open_handler(bind(&WSConnection::OnOpen, this, _1));
|
||||
_client.set_message_handler(
|
||||
bind(&WSConnection::OnMessage, this, _1, _2));
|
||||
UseOBSWebsocketProtocol(useOBSProtocol);
|
||||
_client.set_close_handler(bind(&WSConnection::OnClose, this, _1));
|
||||
}
|
||||
|
||||
|
|
@ -180,31 +179,43 @@ void WSConnection::Disconnect()
|
|||
_status = Status::DISCONNECTED;
|
||||
}
|
||||
|
||||
void WSConnection::SendRequest(const std::string &msg)
|
||||
static std::string constructVendorRequestMessage(const std::string &message,
|
||||
const std::string &uri)
|
||||
{
|
||||
auto request = obs_data_create();
|
||||
obs_data_set_int(request, "op", 6);
|
||||
auto *data = obs_data_create();
|
||||
obs_data_set_string(data, "requestType", "CallVendorRequest");
|
||||
obs_data_set_string(data, "requestId", (msg + " - " + _uri).c_str());
|
||||
obs_data_set_string(data, "requestId", (message + " - " + uri).c_str());
|
||||
|
||||
auto vendorData = obs_data_create();
|
||||
obs_data_set_string(vendorData, "vendorName", VendorName);
|
||||
obs_data_set_string(vendorData, "requestType", VendorRequest);
|
||||
|
||||
auto msgObj = obs_data_create();
|
||||
obs_data_set_string(msgObj, "message", msg.c_str());
|
||||
obs_data_set_string(msgObj, "message", message.c_str());
|
||||
obs_data_set_obj(vendorData, "requestData", msgObj);
|
||||
obs_data_set_obj(data, "requestData", vendorData);
|
||||
|
||||
obs_data_set_obj(request, "d", data);
|
||||
const std::string response(obs_data_get_json(request));
|
||||
|
||||
const std::string result(obs_data_get_json(request));
|
||||
|
||||
obs_data_release(msgObj);
|
||||
obs_data_release(vendorData);
|
||||
obs_data_release(data);
|
||||
obs_data_release(request);
|
||||
|
||||
Send(response);
|
||||
return result;
|
||||
}
|
||||
|
||||
void WSConnection::SendRequest(const std::string &msg)
|
||||
{
|
||||
if (_useOBSProtocol) {
|
||||
Send(constructVendorRequestMessage(msg, _uri));
|
||||
} else {
|
||||
Send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
WSConnection::Status WSConnection::GetStatus() const
|
||||
|
|
@ -212,7 +223,26 @@ WSConnection::Status WSConnection::GetStatus() const
|
|||
return _status;
|
||||
}
|
||||
|
||||
void WSConnection::OnOpen(connection_hdl)
|
||||
void WSConnection::UseOBSWebsocketProtocol(bool useOBSProtocol)
|
||||
{
|
||||
_useOBSProtocol = useOBSProtocol;
|
||||
_client.set_open_handler(bind(useOBSProtocol
|
||||
? &WSConnection::OnOBSOpen
|
||||
: &WSConnection::OnGenericOpen,
|
||||
this, _1));
|
||||
_client.set_message_handler(
|
||||
bind(useOBSProtocol ? &WSConnection::OnOBSMessage
|
||||
: &WSConnection::OnGenericMessage,
|
||||
this, _1, _2));
|
||||
}
|
||||
|
||||
void WSConnection::OnGenericOpen(connection_hdl hdl)
|
||||
{
|
||||
blog(LOG_INFO, "connection to %s opened", _uri.c_str());
|
||||
_status = Status::AUTHENTICATED;
|
||||
}
|
||||
|
||||
void WSConnection::OnOBSOpen(connection_hdl)
|
||||
{
|
||||
blog(LOG_INFO, "connection to %s opened", _uri.c_str());
|
||||
_status = Status::CONNECTING;
|
||||
|
|
@ -294,7 +324,23 @@ void WSConnection::HandleResponse(obs_data_t *response)
|
|||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void WSConnection::OnMessage(connection_hdl, client::message_ptr message)
|
||||
void WSConnection::OnGenericMessage(connection_hdl hdl,
|
||||
client::message_ptr message)
|
||||
{
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
if (message->get_opcode() != websocketpp::frame::opcode::text) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
const auto payload = message->get_payload();
|
||||
_messages.emplace_back(payload);
|
||||
vblog(LOG_INFO, "received event msg \"%s\"", payload.c_str());
|
||||
}
|
||||
|
||||
void WSConnection::OnOBSMessage(connection_hdl, client::message_ptr message)
|
||||
{
|
||||
if (!message) {
|
||||
return;
|
||||
|
|
@ -305,7 +351,7 @@ void WSConnection::OnMessage(connection_hdl, client::message_ptr message)
|
|||
|
||||
std::string payload = message->get_payload();
|
||||
const char *msg = payload.c_str();
|
||||
obs_data_t *json = obs_data_create_from_json(msg);
|
||||
auto json = obs_data_create_from_json(msg);
|
||||
if (!json) {
|
||||
blog(LOG_ERROR, "invalid JSON payload received for '%s'", msg);
|
||||
obs_data_release(json);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ void SendWebsocketEvent(const std::string &);
|
|||
|
||||
class WSConnection : public QObject {
|
||||
public:
|
||||
explicit WSConnection();
|
||||
explicit WSConnection(bool useOBSProtocol = true);
|
||||
virtual ~WSConnection();
|
||||
|
||||
void Connect(const std::string &uri, const std::string &pass,
|
||||
|
|
@ -50,10 +50,13 @@ public:
|
|||
AUTHENTICATED,
|
||||
};
|
||||
Status GetStatus() const;
|
||||
void UseOBSWebsocketProtocol(bool);
|
||||
|
||||
private:
|
||||
void OnOpen(connection_hdl hdl);
|
||||
void OnMessage(connection_hdl hdl, client::message_ptr message);
|
||||
void OnGenericOpen(connection_hdl hdl);
|
||||
void OnOBSOpen(connection_hdl hdl);
|
||||
void OnGenericMessage(connection_hdl hdl, client::message_ptr message);
|
||||
void OnOBSMessage(connection_hdl hdl, client::message_ptr message);
|
||||
void OnClose(connection_hdl hdl);
|
||||
void Send(const std::string &);
|
||||
void ConnectThread();
|
||||
|
|
@ -76,6 +79,7 @@ private:
|
|||
std::atomic_bool _disconnect{false};
|
||||
|
||||
std::vector<std::string> _messages;
|
||||
bool _useOBSProtocol = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user