diff --git a/AUTHORS b/AUTHORS index a3966eadc..bc9a08bcd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -34,3 +34,4 @@ Contributors: Stefan S, improved timing with monotonic clock Tobi Schäfer, for the MacPort files Tor Håkon Gjerde, added AVLdiy D512 support + Alexander Simon, added SIUDI support diff --git a/debian/ola.udev b/debian/ola.udev index 40532ddfa..b27ded1ec 100644 --- a/debian/ola.udev +++ b/debian/ola.udev @@ -43,5 +43,8 @@ SUBSYSTEM=="usb|usb_device", ACTION=="add", ATTRS{idVendor}=="1d50", ATTRS{idPro SUBSYSTEM=="usb|usb_device", ACTION=="add", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="aced", GROUP="plugdev", MODE="660", TAG+="uaccess" SUBSYSTEM=="usb|usb_device", ACTION=="add", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="acee", GROUP="plugdev", MODE="660", TAG+="uaccess" +# udev rules for Nicoleaudie Intelligent USB DMX Interface (SIUDI) +SUBSYSTEM=="usb|usb_device", ACTION=="add", ATTRS{idVendor}=="6244", ATTRS{idProduct}=="030?", GROUP="plugdev", MODE="660", TAG+="uaccess" + # udev rules for SPI SUBSYSTEM=="spidev", MODE="0666" diff --git a/debian/org.openlighting.ola.ola.metainfo.xml b/debian/org.openlighting.ola.ola.metainfo.xml index 8a663fc06..5436067a5 100644 --- a/debian/org.openlighting.ola.ola.metainfo.xml +++ b/debian/org.openlighting.ola.ola.metainfo.xml @@ -35,6 +35,7 @@ usb:v1D50p607Ad* usb:v109pACEDd* usb:v109pACEEd* + usb:v6244p030*d* lkmodule:spidev lkmodule:dmxi2c lkmodule:okdmx diff --git a/plugins/usbdmx/AsyncPluginImpl.cpp b/plugins/usbdmx/AsyncPluginImpl.cpp index c7bd75bfa..2bd0a68a5 100644 --- a/plugins/usbdmx/AsyncPluginImpl.cpp +++ b/plugins/usbdmx/AsyncPluginImpl.cpp @@ -53,6 +53,7 @@ #include "plugins/usbdmx/ScanlimeFadecandy.h" #include "plugins/usbdmx/ScanlimeFadecandyFactory.h" #include "plugins/usbdmx/ShowJockeyDMXU1Factory.h" +#include "plugins/usbdmx/SiudiFactory.h" #include "plugins/usbdmx/SunliteFactory.h" #include "plugins/usbdmx/VellemanK8062.h" #include "plugins/usbdmx/VellemanK8062Factory.h" @@ -132,6 +133,7 @@ bool AsyncPluginImpl::Start() { m_widget_factories.push_back( new ScanlimeFadecandyFactory(m_usb_adaptor)); m_widget_factories.push_back(new ShowJockeyDMXU1Factory(m_usb_adaptor)); + m_widget_factories.push_back(new SiudiFactory(m_usb_adaptor)); m_widget_factories.push_back(new SunliteFactory(m_usb_adaptor)); m_widget_factories.push_back(new VellemanK8062Factory(m_usb_adaptor)); @@ -233,6 +235,12 @@ bool AsyncPluginImpl::NewWidget(ShowJockeyDMXU1 *widget) { "showjockey-dmx-u1-" + widget->SerialNumber())); } +bool AsyncPluginImpl::NewWidget(Siudi *widget) { + return StartAndRegisterDevice( + widget, + new GenericDevice(m_plugin, widget, "Nicolaudie SIUDI", "usbsiudi")); +} + bool AsyncPluginImpl::NewWidget(Sunlite *widget) { return StartAndRegisterDevice( widget, diff --git a/plugins/usbdmx/AsyncPluginImpl.h b/plugins/usbdmx/AsyncPluginImpl.h index 56282281c..7fec41109 100644 --- a/plugins/usbdmx/AsyncPluginImpl.h +++ b/plugins/usbdmx/AsyncPluginImpl.h @@ -85,6 +85,7 @@ class AsyncPluginImpl: public PluginImplInterface, public WidgetObserver { bool NewWidget(ola::usb::JaRuleWidget *widget); bool NewWidget(class ScanlimeFadecandy *widget); bool NewWidget(class ShowJockeyDMXU1 *widget); + bool NewWidget(class Siudi *widget); bool NewWidget(class Sunlite *widget); bool NewWidget(class VellemanK8062 *widget); diff --git a/plugins/usbdmx/Makefile.mk b/plugins/usbdmx/Makefile.mk index daf83a229..536bac3d0 100644 --- a/plugins/usbdmx/Makefile.mk +++ b/plugins/usbdmx/Makefile.mk @@ -49,6 +49,10 @@ plugins_usbdmx_libolausbdmxwidget_la_SOURCES = \ plugins/usbdmx/ShowJockeyDMXU1.h \ plugins/usbdmx/ShowJockeyDMXU1Factory.cpp \ plugins/usbdmx/ShowJockeyDMXU1Factory.h \ + plugins/usbdmx/Siudi.cpp \ + plugins/usbdmx/Siudi.h \ + plugins/usbdmx/SiudiFactory.cpp \ + plugins/usbdmx/SiudiFactory.h \ plugins/usbdmx/Sunlite.cpp \ plugins/usbdmx/Sunlite.h \ plugins/usbdmx/SunliteFactory.cpp \ diff --git a/plugins/usbdmx/README.md b/plugins/usbdmx/README.md index 04696f1c3..e02a2e2f7 100644 --- a/plugins/usbdmx/README.md +++ b/plugins/usbdmx/README.md @@ -15,6 +15,7 @@ This plugin supports various USB DMX devices including: * FX5 DMX * ShowJockey SJ-DMX-U1 * Sunlite USBDMX2 +* Nicoleaudie Sunlite intelligent USB DMX interface (SIUDI) (also ADJ MyDMX) * Velleman K8062. diff --git a/plugins/usbdmx/Siudi.cpp b/plugins/usbdmx/Siudi.cpp new file mode 100644 index 000000000..33429cf75 --- /dev/null +++ b/plugins/usbdmx/Siudi.cpp @@ -0,0 +1,174 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Siudi.cpp + * The synchronous SIUDI widgets. + * Copyright (C) 2023 Alexander Simon + */ + +#include "plugins/usbdmx/Siudi.h" + +#include +#include + +#include "libs/usb/LibUsbAdaptor.h" +#include "ola/Constants.h" +#include "ola/Logging.h" +#include "ola/strings/Format.h" +#include "plugins/usbdmx/AsyncUsbSender.h" +#include "plugins/usbdmx/ThreadedUsbSender.h" + +namespace ola { +namespace plugin { +namespace usbdmx { + +using ola::usb::LibUsbAdaptor; + +namespace { + +static const uint8_t ENDPOINT = 2; +// SIUDI-6 blocks USB transfers during an ongoing DMX TX. +// One package needs about 32 ms to be sent. +// Wait 30 ms between two USB bulk transfers and expect 2 ms USB response delay. +static const unsigned int BULK_TIMEOUT = 10; +static const unsigned int BULK_DELAY = (30 * 1000); +static const unsigned int CONTROL_TIMEOUT = 500; +static const unsigned int DEVINFO_REQUEST = 0x3f; +static const unsigned int DEVINFO_SIZE = 64; + +} // namespace + +// SiudiThreadedSender +// ----------------------------------------------------------------------------- + +/* + * Sends messages to a SIUDI device in a separate thread. + */ +class SiudiThreadedSender: public ThreadedUsbSender { + public: + SiudiThreadedSender(LibUsbAdaptor *adaptor, + libusb_device *usb_device, + libusb_device_handle *handle); + + bool Start(); + +private: + LibUsbAdaptor* const m_adaptor; + libusb_device_handle* const m_usb_handle; + + bool TransmitBuffer(libusb_device_handle *handle, + const DmxBuffer &buffer); +}; + +SiudiThreadedSender::SiudiThreadedSender( + LibUsbAdaptor *adaptor, + libusb_device *usb_device, + libusb_device_handle *usb_handle) + : ThreadedUsbSender(usb_device, usb_handle), + m_adaptor(adaptor), m_usb_handle(usb_handle) { +} + +bool SiudiThreadedSender::Start() { + if (!ThreadedUsbSender::Start()) { + return false; + } + + // Read device info. This call takes about 270 ms. + // Discard the buffer as the format is currently unknown. + uint8_t buf[DEVINFO_SIZE]; + int ret = libusb_control_transfer(m_usb_handle, + LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN, + DEVINFO_REQUEST, 0x0000, 1, buf, DEVINFO_SIZE, CONTROL_TIMEOUT); + if (ret != DEVINFO_SIZE) { + OLA_WARN << "Failed to read SIUDI information: " + << (ret < 0 ? LibUsbAdaptor::ErrorCodeToString(ret) : "Short read"); + return false; + } + if (ola::OLA_LOG_DEBUG <= ola::LogLevel()) { + ola::LogLine(__FILE__, __LINE__, ola::OLA_LOG_DEBUG).stream() << "SIUDI device info:"; + ola::strings::FormatData(&std::cout, buf, DEVINFO_SIZE, 4); + ola::LogLine(__FILE__, __LINE__, ola::OLA_LOG_DEBUG).stream() << "If you know how to interprete this, please let us know."; + } + + // Unstall the endpoint. The original software seems to call this regularly. + ret = libusb_clear_halt(m_usb_handle, ENDPOINT); + if (ret != 0) { + OLA_WARN << "Failed to reset SIUDI endpoint: " + << (ret < 0 ? LibUsbAdaptor::ErrorCodeToString(ret) : "Unknown"); + return false; + } + usleep(BULK_DELAY); // Might receive errors if writing too early. + + return true; +} + +bool SiudiThreadedSender::TransmitBuffer(libusb_device_handle *handle, + const DmxBuffer &buffer) { + int transferred, r; + if (buffer.Size() == ola::DMX_UNIVERSE_SIZE) { + // As we are sending, we can cast the const buffer to a writeable pointer. + r = m_adaptor->BulkTransfer( + handle, ENDPOINT, (unsigned char*)buffer.GetRaw(), + ola::DMX_UNIVERSE_SIZE, &transferred, BULK_TIMEOUT); + } else { + unsigned char buf[ola::DMX_UNIVERSE_SIZE]; + unsigned int buf_get_size = ola::DMX_UNIVERSE_SIZE; + buffer.GetRange(0, buf, &buf_get_size); + if (buf_get_size < ola::DMX_UNIVERSE_SIZE) { + memset(&buf[buf_get_size], 0x00, ola::DMX_UNIVERSE_SIZE - buf_get_size); + } + r = m_adaptor->BulkTransfer( + handle, ENDPOINT, buf, ola::DMX_UNIVERSE_SIZE, &transferred, BULK_TIMEOUT); + } + if (transferred != ola::DMX_UNIVERSE_SIZE) { + // not sure if this is fatal or not + OLA_WARN << "SIUDI driver failed to transfer all data"; + } + usleep(BULK_DELAY); + return r == 0; +} + +// SynchronousSiudi +// ----------------------------------------------------------------------------- + +SynchronousSiudi::SynchronousSiudi(LibUsbAdaptor *adaptor, + libusb_device *usb_device) + : Siudi(adaptor, usb_device) { +} + +bool SynchronousSiudi::Init() { + libusb_device_handle *usb_handle; + + bool ok = m_adaptor->OpenDeviceAndClaimInterface( + m_usb_device, 0, &usb_handle); + if (!ok) { + return false; + } + + std::auto_ptr sender( + new SiudiThreadedSender(m_adaptor, m_usb_device, usb_handle)); + if (!sender->Start()) { + return false; + } + m_sender.reset(sender.release()); + return true; +} + +bool SynchronousSiudi::SendDMX(const DmxBuffer &buffer) { + return m_sender.get() ? m_sender->SendDMX(buffer) : false; +} +} // namespace usbdmx +} // namespace plugin +} // namespace ola diff --git a/plugins/usbdmx/Siudi.h b/plugins/usbdmx/Siudi.h new file mode 100644 index 000000000..22c52e19b --- /dev/null +++ b/plugins/usbdmx/Siudi.h @@ -0,0 +1,76 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Siudi.h + * The synchronous SIUDI widgets. + * Copyright (C) 2023 Alexander Simon + */ + +#ifndef PLUGINS_USBDMX_SIUDI_H_ +#define PLUGINS_USBDMX_SIUDI_H_ + +#include +#include +#include "ola/DmxBuffer.h" +#include "ola/base/Macro.h" +#include "ola/thread/Mutex.h" +#include "plugins/usbdmx/Widget.h" + +namespace ola { +namespace plugin { +namespace usbdmx { + +class SiudiThreadedSender; + +/** + * @brief The interface for the Siudi Widgets + */ +class Siudi : public SimpleWidget { + public: + explicit Siudi(ola::usb::LibUsbAdaptor *adaptor, + libusb_device *usb_device) + : SimpleWidget(adaptor, usb_device) { + } +}; + + +/** + * @brief An SIUDI widget that uses synchronous libusb operations. + * + * Internally this spawns a new thread to avoid blocking SendDMX() calls. + */ +class SynchronousSiudi: public Siudi { + public: + /** + * @brief Create a new SynchronousSiudi. + * @param adaptor the LibUsbAdaptor to use. + * @param usb_device the libusb_device to use for the widget. + */ + SynchronousSiudi(ola::usb::LibUsbAdaptor *adaptor, + libusb_device *usb_device); + + bool Init(); + + bool SendDMX(const DmxBuffer &buffer); + + private: + std::auto_ptr m_sender; + + DISALLOW_COPY_AND_ASSIGN(SynchronousSiudi); +}; +} // namespace usbdmx +} // namespace plugin +} // namespace ola +#endif // PLUGINS_USBDMX_SIUDI_H_ diff --git a/plugins/usbdmx/SiudiFactory.cpp b/plugins/usbdmx/SiudiFactory.cpp new file mode 100644 index 000000000..8f4e4e5e4 --- /dev/null +++ b/plugins/usbdmx/SiudiFactory.cpp @@ -0,0 +1,68 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * SiudiFactory.cpp + * The WidgetFactory for SIUDI widgets. + * Copyright (C) 2023 Alexander Simon + */ + +#include "plugins/usbdmx/SiudiFactory.h" + +#include "ola/Logging.h" +#include "ola/base/Flags.h" + +DECLARE_bool(use_async_libusb); + +namespace ola { +namespace plugin { +namespace usbdmx { + +const uint16_t SiudiFactory::NICOLAUDIE_ID = 0x6244; +const uint16_t SiudiFactory::SIUDI6_COLD_ID = 0x0300; +const uint16_t SiudiFactory::SIUDI6C_HOT_ID = 0x301; +const uint16_t SiudiFactory::SIUDI6A_HOT_ID = 0x302; +const uint16_t SiudiFactory::SIUDI6D_HOT_ID = 0x303; + +bool SiudiFactory::DeviceAdded( + WidgetObserver *observer, + libusb_device *usb_device, + const struct libusb_device_descriptor &descriptor) { + if (descriptor.idVendor != NICOLAUDIE_ID) { + return false; + } + if (descriptor.idProduct == SIUDI6_COLD_ID) { + OLA_WARN << "Found a Nicoleaudie SIUDI-6 device in cold state. " + "Firmware download is currently not supported."; + return false; + } + if (descriptor.idProduct == SIUDI6C_HOT_ID || + descriptor.idProduct == SIUDI6A_HOT_ID || + descriptor.idProduct == SIUDI6D_HOT_ID) { + if (descriptor.idProduct == SIUDI6C_HOT_ID) { + OLA_INFO << "Found a new Nicoleaudie SIUDI-6C device"; + } else if (descriptor.idProduct == SIUDI6A_HOT_ID) { + OLA_INFO << "Found a new Nicoleaudie SIUDI-6A device"; + } else if (descriptor.idProduct == SIUDI6D_HOT_ID) { + OLA_INFO << "Found a new Nicoleaudie SIUDI-6D device"; + } + Siudi *widget = NULL; + widget = new SynchronousSiudi(m_adaptor, usb_device); + return AddWidget(observer, widget); + } + return false; +} +} // namespace usbdmx +} // namespace plugin +} // namespace ola diff --git a/plugins/usbdmx/SiudiFactory.h b/plugins/usbdmx/SiudiFactory.h new file mode 100644 index 000000000..5b8c6c102 --- /dev/null +++ b/plugins/usbdmx/SiudiFactory.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * SiudiFactory.h + * The WidgetFactory for SIUDI widgets. + * Copyright (C) 2023 Alexander Simon + */ + +#ifndef PLUGINS_USBDMX_SIUDIFACTORY_H_ +#define PLUGINS_USBDMX_SIUDIFACTORY_H_ + +#include "libs/usb/LibUsbAdaptor.h" +#include "ola/base/Macro.h" +#include "plugins/usbdmx/Siudi.h" +#include "plugins/usbdmx/Siudi.h" +#include "plugins/usbdmx/WidgetFactory.h" + +namespace ola { +namespace plugin { +namespace usbdmx { + +/** + * @brief Creates SunLite widgets. + */ +class SiudiFactory : public BaseWidgetFactory { + public: + explicit SiudiFactory(ola::usb::LibUsbAdaptor *adaptor) + : BaseWidgetFactory("SiudiFactory"), + m_adaptor(adaptor) {} + + bool DeviceAdded( + WidgetObserver *observer, + libusb_device *usb_device, + const struct libusb_device_descriptor &descriptor); + + private: + ola::usb::LibUsbAdaptor* const m_adaptor; + + static const uint16_t NICOLAUDIE_ID; + // The product ID for widgets that are missing their firmware. + static const uint16_t SIUDI6_COLD_ID; + // The product ID for widgets with the firmware. + static const uint16_t SIUDI6C_HOT_ID; + static const uint16_t SIUDI6A_HOT_ID; + static const uint16_t SIUDI6D_HOT_ID; + + DISALLOW_COPY_AND_ASSIGN(SiudiFactory); +}; +} // namespace usbdmx +} // namespace plugin +} // namespace ola +#endif // PLUGINS_USBDMX_SIUDIFACTORY_H_ diff --git a/plugins/usbdmx/SyncPluginImpl.cpp b/plugins/usbdmx/SyncPluginImpl.cpp index 99c5a19c3..3b759c444 100644 --- a/plugins/usbdmx/SyncPluginImpl.cpp +++ b/plugins/usbdmx/SyncPluginImpl.cpp @@ -50,6 +50,8 @@ #include "plugins/usbdmx/GenericDevice.h" #include "plugins/usbdmx/ShowJockeyDMXU1.h" #include "plugins/usbdmx/ShowJockeyDMXU1Factory.h" +#include "plugins/usbdmx/Siudi.h" +#include "plugins/usbdmx/SiudiFactory.h" #include "plugins/usbdmx/Sunlite.h" #include "plugins/usbdmx/SunliteFactory.h" #include "plugins/usbdmx/VellemanK8062.h" @@ -81,6 +83,7 @@ SyncPluginImpl::SyncPluginImpl(PluginAdaptor *plugin_adaptor, m_preferences)); m_widget_factories.push_back(new ScanlimeFadecandyFactory(&m_usb_adaptor)); m_widget_factories.push_back(new ShowJockeyDMXU1Factory(&m_usb_adaptor)); + m_widget_factories.push_back(new SiudiFactory(&m_usb_adaptor)); m_widget_factories.push_back(new SunliteFactory(&m_usb_adaptor)); m_widget_factories.push_back(new VellemanK8062Factory(&m_usb_adaptor)); } @@ -192,6 +195,12 @@ bool SyncPluginImpl::NewWidget(ShowJockeyDMXU1 *widget) { "showjockey-dmx-u1-" + widget->SerialNumber())); } +bool SyncPluginImpl::NewWidget(Siudi *widget) { + return StartAndRegisterDevice( + widget, + new GenericDevice(m_plugin, widget, "Sunlite SIUDI", "usbsiudi")); +} + bool SyncPluginImpl::NewWidget(Sunlite *widget) { return StartAndRegisterDevice( widget, diff --git a/plugins/usbdmx/SyncPluginImpl.h b/plugins/usbdmx/SyncPluginImpl.h index 92694b546..df01e04c8 100644 --- a/plugins/usbdmx/SyncPluginImpl.h +++ b/plugins/usbdmx/SyncPluginImpl.h @@ -79,6 +79,7 @@ class SyncPluginImpl: public PluginImplInterface, public WidgetObserver { bool NewWidget(ola::usb::JaRuleWidget *widget); bool NewWidget(class ScanlimeFadecandy *widget); bool NewWidget(class ShowJockeyDMXU1 *widget); + bool NewWidget(class Siudi *widget); bool NewWidget(class Sunlite *widget); bool NewWidget(class VellemanK8062 *widget); @@ -90,6 +91,7 @@ class SyncPluginImpl: public PluginImplInterface, public WidgetObserver { void WidgetRemoved(OLA_UNUSED ola::usb::JaRuleWidget *widget) {} void WidgetRemoved(OLA_UNUSED class ScanlimeFadecandy *widget) {} void WidgetRemoved(OLA_UNUSED class ShowJockeyDMXU1 *widget) {} + void WidgetRemoved(OLA_UNUSED class Siudi *widget) {} void WidgetRemoved(OLA_UNUSED class Sunlite *widget) {} void WidgetRemoved(OLA_UNUSED class VellemanK8062 *widget) {} diff --git a/plugins/usbdmx/SynchronizedWidgetObserver.h b/plugins/usbdmx/SynchronizedWidgetObserver.h index 227551f04..0f3bf009d 100644 --- a/plugins/usbdmx/SynchronizedWidgetObserver.h +++ b/plugins/usbdmx/SynchronizedWidgetObserver.h @@ -79,6 +79,10 @@ class SynchronizedWidgetObserver : public WidgetObserver { return DispatchNewWidget(widget); } + bool NewWidget(class Siudi *widget) { + return DispatchNewWidget(widget); + } + bool NewWidget(class Sunlite *widget) { return DispatchNewWidget(widget); } diff --git a/plugins/usbdmx/UsbDmxPlugin.h b/plugins/usbdmx/UsbDmxPlugin.h index 8e7e40346..db6e41973 100644 --- a/plugins/usbdmx/UsbDmxPlugin.h +++ b/plugins/usbdmx/UsbDmxPlugin.h @@ -43,7 +43,8 @@ namespace usbdmx { * - Eurolite DMX USB Pro. * - Eurolite DMX USB Pro MK2. * - Scanlime's Fadecandy. - * - Sunlite. + * - Sunlite SIUDI. + * - Sunlite USBDMX2. * - Velleman K8062. */ class UsbDmxPlugin: public ola::Plugin { diff --git a/plugins/usbdmx/WidgetFactory.h b/plugins/usbdmx/WidgetFactory.h index a7a00c5b7..065cc478c 100644 --- a/plugins/usbdmx/WidgetFactory.h +++ b/plugins/usbdmx/WidgetFactory.h @@ -122,6 +122,15 @@ class WidgetObserver { */ virtual bool NewWidget(class ScanlimeFadecandy *widget) = 0; + /** + * @brief Called when a new SIUDI device is added. + * @param widget the new Widget, ownership is not transferred but the object + * may be used until the corresponding WidgetRemoved() call is made. + * @returns true if the widget has been claimed, false if the widget was + * ignored. + */ + virtual bool NewWidget(class Siudi *widget) = 0; + /** * @brief Called when a new Sunlite is added. * @param widget the new Widget, ownership is not transferred but the object