Skip to content

Commit

Permalink
[protocols] Prevent adding dummy devices when it does not make sense
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Aug 5, 2024
1 parent c0776f3 commit 1e93659
Show file tree
Hide file tree
Showing 29 changed files with 145 additions and 66 deletions.
2 changes: 1 addition & 1 deletion src/plugins/score-plugin-audio/Audio/AudioDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ void AudioProtocolFactory::serializeProtocolSpecificSettings(
bool AudioProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

AudioSettingsWidget::AudioSettingsWidget(QWidget* parent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,20 @@ bool DeviceExplorerModel::checkDeviceInstantiatable(
return false;

// Look for other childs in the same protocol.
return std::none_of(
bool none_incompatible = std::none_of(
rootNode().begin(), rootNode().end(), [&](const Device::Node& child) {
SCORE_ASSERT(child.is<Device::DeviceSettings>());
const auto& set = child.get<Device::DeviceSettings>();
return (set.name == n.name)
|| (set.protocol == n.protocol
&& !prot->checkCompatibility(n, child.get<Device::DeviceSettings>()));
});
SCORE_ASSERT(child.is<Device::DeviceSettings>());
const auto& set = child.get<Device::DeviceSettings>();
return (set.name == n.name)
|| (set.protocol
== n.protocol // FIXME distinct protocols could use the same port...
&& !prot->checkCompatibility(n, child.get<Device::DeviceSettings>()));
});
if(!none_incompatible)
return false;

// Check compatibility with an empty device
return prot->checkCompatibility(n, Device::DeviceSettings{});
}

bool DeviceExplorerModel::checkDeviceEditable(
Expand All @@ -267,18 +273,23 @@ bool DeviceExplorerModel::checkDeviceEditable(
return false;

// Look for other childs in the same protocol.
return std::none_of(
bool none_incompatible = std::none_of(
rootNode().begin(), rootNode().end(), [&](const Device::Node& child) {
SCORE_ASSERT(child.is<Device::DeviceSettings>());
const auto& set = child.get<Device::DeviceSettings>();
// Ignore the device that is being edited
if(set.name == originalName)
return false;

return (set.name == n.name)
|| (set.protocol == n.protocol
&& !prot->checkCompatibility(n, child.get<Device::DeviceSettings>()));
});
SCORE_ASSERT(child.is<Device::DeviceSettings>());
const auto& set = child.get<Device::DeviceSettings>();
// Ignore the device that is being edited
if(set.name == originalName)
return false;

return (set.name == n.name)
|| (set.protocol == n.protocol
&& !prot->checkCompatibility(n, child.get<Device::DeviceSettings>()));
});
if(!none_incompatible)
return false;

// Check compatibility with an empty device
return prot->checkCompatibility(n, Device::DeviceSettings{});
}

bool DeviceExplorerModel::checkAddressInstantiatable(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ void LocalProtocolFactory::serializeProtocolSpecificSettings(
bool LocalProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

}
2 changes: 1 addition & 1 deletion src/plugins/score-plugin-gfx/Gfx/CameraDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void CameraProtocolFactory::serializeProtocolSpecificSettings(
bool CameraProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

class CameraSettingsWidget final : public Device::ProtocolSettingsWidget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ void LibavOutputProtocolFactory::serializeProtocolSpecificSettings(
bool LibavOutputProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

LibavOutputSettingsWidget::LibavOutputSettingsWidget(QWidget* parent)
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/score-plugin-gfx/Gfx/SharedInputSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void SharedInputProtocolFactory::serializeProtocolSpecificSettings(
bool SharedInputProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

SharedInputSettingsWidget::SharedInputSettingsWidget(QWidget* parent)
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/score-plugin-gfx/Gfx/SharedOutputSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void SharedOutputProtocolFactory::serializeProtocolSpecificSettings(
bool SharedOutputProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

SharedOutputSettingsWidget::SharedOutputSettingsWidget(QWidget* parent)
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/score-plugin-gfx/Gfx/WindowDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ void WindowProtocolFactory::serializeProtocolSpecificSettings(
bool WindowProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}

WindowSettingsWidget::WindowSettingsWidget(QWidget* parent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ void ArtnetProtocolFactory::serializeProtocolSpecificSettings(
bool ArtnetProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
if(a.name == b.name)
return false;
if(a.protocol != b.protocol)
return true;
auto lhs = a.deviceSpecificSettings.value<ArtnetSpecificSettings>();
auto rhs = b.deviceSpecificSettings.value<ArtnetSpecificSettings>();
if(lhs.transport != rhs.transport)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void GPSProtocolFactory::serializeProtocolSpecificSettings(
bool GPSProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return false; // TODO
return true; // TODO
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ void HTTPProtocolFactory::serializeProtocolSpecificSettings(
bool HTTPProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
return a.name != b.name;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <score/document/DocumentContext.hpp>

#include <ossia/protocols/joystick/game_controller_protocol.hpp>
#include <ossia/protocols/joystick/joystick_protocol.hpp>

#include <wobjectimpl.h>
Expand All @@ -29,20 +30,17 @@ JoystickDevice::JoystickDevice(

JoystickDevice::~JoystickDevice() { }

bool JoystickDevice::reconnect()
template <typename T>
void JoystickDevice::do_reconnect(JoystickSpecificSettings& stgs)
{
disconnect();

auto stgs = settings().deviceSpecificSettings.value<JoystickSpecificSettings>();
try
{
m_dev = std::make_unique<ossia::net::generic_device>(
std::make_unique<ossia::net::joystick_protocol>(
m_ctx, stgs.spec.first, stgs.spec.second),
std::make_unique<T>(m_ctx, stgs.spec.first, stgs.spec.second),
settings().name.toStdString());
deviceChanged(nullptr, m_dev.get());
}
catch(...)
catch(const std::runtime_error&)
{
// Maybe the joystick has become unavailable. Try to find a similar available one just once.
try
Expand All @@ -51,8 +49,7 @@ bool JoystickDevice::reconnect()
if(stgs.spec != stgs.unassigned)
{
m_dev = std::make_unique<ossia::net::generic_device>(
std::make_unique<ossia::net::joystick_protocol>(
m_ctx, stgs.spec.first, stgs.spec.second),
std::make_unique<T>(m_ctx, stgs.spec.first, stgs.spec.second),
settings().name.toStdString());

// update the settings with the new spec...
Expand All @@ -61,11 +58,39 @@ bool JoystickDevice::reconnect()
deviceChanged(nullptr, m_dev.get());
}
}
catch(...)
catch(const std::runtime_error&)
{
SCORE_TODO;
throw;
}
}
}
bool JoystickDevice::reconnect()
{
disconnect();

auto stgs = settings().deviceSpecificSettings.value<JoystickSpecificSettings>();
try
{
if(stgs.gamepad)
{
try
{
do_reconnect<ossia::net::game_controller_protocol>(stgs);
}
catch(...)
{
do_reconnect<ossia::net::joystick_protocol>(stgs);
}
}
else
{
do_reconnect<ossia::net::joystick_protocol>(stgs);
}
}
catch(...)
{
SCORE_TODO;
}

return connected();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Protocols
{

struct JoystickSpecificSettings;
class JoystickDevice final : public Device::OwningDeviceInterface
{
W_OBJECT(JoystickDevice)
Expand All @@ -17,6 +17,8 @@ class JoystickDevice final : public Device::OwningDeviceInterface
void disconnect() override;

private:
template <typename T>
void do_reconnect(JoystickSpecificSettings& stgs);
const ossia::net::network_context_ptr& m_ctx;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ class JoystickEnumerator : public Device::DeviceEnumerator
void enumerate(std::function<void(const QString&, const Device::DeviceSettings&)> f)
const override
{
const unsigned int joystick_count = ossia::net::joystick_info::get_joystick_count();
using info = ossia::net::joystick_info;
const unsigned int joystick_count = info::get_joystick_count();

for(unsigned int i = 0; i < joystick_count; ++i)
{
const char* s = ossia::net::joystick_info::get_joystick_name(i);
const char* s = info::get_joystick_name(i);
if(s)
{
Device::DeviceSettings set;
set.name = s;
set.protocol = JoystickProtocolFactory::static_concreteKey();
JoystickSpecificSettings specif;
ossia::net::joystick_info::write_joystick_uuid(i, specif.id.data);
specif.spec = {ossia::net::joystick_info::get_joystick_id(i), i};
info::write_joystick_uuid(i, specif.id.data);
specif.spec = {info::get_joystick_id(i), i};
specif.gamepad = info::get_joystick_is_gamepad(i);

set.deviceSpecificSettings = QVariant::fromValue(specif);
f(set.name, set);
Expand Down Expand Up @@ -69,7 +71,10 @@ const Device::DeviceSettings& JoystickProtocolFactory::defaultSettings() const n
Device::DeviceSettings s;
s.protocol = concreteKey();
s.name = "Joystick";

JoystickSpecificSettings settings;
settings.id = {};
settings.spec = {-1, -1};
s.deviceSpecificSettings = QVariant::fromValue(settings);
return s;
}();
Expand Down Expand Up @@ -98,6 +103,16 @@ bool JoystickProtocolFactory::checkCompatibility(
const Device::DeviceSettings& a, const Device::DeviceSettings& b) const noexcept
{
auto a_ = a.deviceSpecificSettings.value<JoystickSpecificSettings>();
if(a.protocol != b.protocol)
{
// Prevent instantiating a dummy joystick device
if(a_.id == score::uuid_t{} && a_.spec == std::pair<int32_t, int32_t>{-1, -1})
{
return false;
}
return true;
}

auto b_ = b.deviceSpecificSettings.value<JoystickSpecificSettings>();
return a_.id != b_.id || a_.spec != b_.spec;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <ossia/protocols/joystick/joystick_protocol.hpp>

#include <QCheckBox>
#include <QFormLayout>
#include <QPushButton>
#include <QVariant>
Expand All @@ -28,8 +29,16 @@ JoystickProtocolSettingsWidget::JoystickProtocolSettingsWidget(QWidget* parent)
checkForChanges(m_deviceNameEdit);
m_deviceNameEdit->setText("Joystick");

m_gamepad = new QCheckBox{this};
m_gamepad->setChecked(false);
m_gamepad->setWhatsThis(
tr("Try to leverage the SDL Gamepad API. This gives access to rumble, "
"accelerometers, etc."));
m_gamepad->setToolTip(m_gamepad->whatsThis());

auto layout = new QFormLayout;
layout->addRow(tr("Name"), m_deviceNameEdit);
layout->addRow(tr("Gamepad API"), m_gamepad);

setLayout(layout);
}
Expand All @@ -41,13 +50,24 @@ Device::DeviceSettings JoystickProtocolSettingsWidget::getSettings() const
Device::DeviceSettings s = m_settings;
s.name = m_deviceNameEdit->text();
s.protocol = JoystickProtocolFactory::static_concreteKey();
if(s.deviceSpecificSettings.canConvert<JoystickSpecificSettings>())
{
auto specif = s.deviceSpecificSettings.value<JoystickSpecificSettings>();
specif.gamepad = m_gamepad->isChecked();
s.deviceSpecificSettings = QVariant::fromValue(specif);
}
return s;
}

void JoystickProtocolSettingsWidget::setSettings(const Device::DeviceSettings& settings)
{
m_settings = settings;
m_deviceNameEdit->setText(settings.name);
if(m_settings.deviceSpecificSettings.canConvert<JoystickSpecificSettings>())
{
auto specif = m_settings.deviceSpecificSettings.value<JoystickSpecificSettings>();
m_gamepad->setChecked(specif.gamepad);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@
#include <verdigris>

class QLineEdit;
namespace score
{
class ComboBox;
}
class QCheckBox;

namespace Protocols
{

class JoystickProtocolSettingsWidget final : public Device::ProtocolSettingsWidget
{
W_OBJECT(JoystickProtocolSettingsWidget)
Expand All @@ -26,6 +22,7 @@ class JoystickProtocolSettingsWidget final : public Device::ProtocolSettingsWidg

protected:
QLineEdit* m_deviceNameEdit{};
QCheckBox* m_gamepad{};
Device::DeviceSettings m_settings;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct JoystickSpecificSettings
// device id, device index
static const constexpr std::pair<int32_t, int32_t> unassigned{-1, -1};
std::pair<int32_t, int32_t> spec{unassigned};

bool gamepad{};
};
}

Expand Down
Loading

0 comments on commit 1e93659

Please sign in to comment.