diff --git a/.github/workflows/bsd.yml b/.github/workflows/bsd.yml index e7529836b7..2085f4b5f6 100644 --- a/.github/workflows/bsd.yml +++ b/.github/workflows/bsd.yml @@ -1,5 +1,9 @@ name: BSDs -on: push +on: [push,pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: build_bsd: diff --git a/.github/workflows/builds.yaml b/.github/workflows/builds.yaml index 779bc5287d..6e967809ba 100644 --- a/.github/workflows/builds.yaml +++ b/.github/workflows/builds.yaml @@ -1,6 +1,10 @@ name: Linux distro build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: fedora: name: Fedora (latest) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 60e21c82c3..a39b5f3420 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -1,9 +1,13 @@ name: Continuous build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: tarball: - name: Tarball + name: Tarball runs-on: ubuntu-latest steps: - name: Checkout code @@ -44,7 +48,7 @@ jobs: staging/*.* appimage: - name: AppImage + name: AppImage runs-on: ubuntu-latest steps: - name: Checkout code @@ -154,7 +158,7 @@ jobs: win32: - name: Windows + name: Windows runs-on: windows-latest steps: - name: Checkout code diff --git a/.github/workflows/debian-builds.yaml b/.github/workflows/debian-builds.yaml index a5d07ff639..d271ec8aa0 100644 --- a/.github/workflows/debian-builds.yaml +++ b/.github/workflows/debian-builds.yaml @@ -1,6 +1,10 @@ name: Debian build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: debian: name: Debian diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 2a1e003634..d56478bd2b 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -1,5 +1,9 @@ name: Documentation build +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: push: branches: diff --git a/.github/workflows/embedded.yaml b/.github/workflows/embedded.yaml index 7a6b0db782..32ffebb3a7 100644 --- a/.github/workflows/embedded.yaml +++ b/.github/workflows/embedded.yaml @@ -1,6 +1,10 @@ name: Embedded build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: # rpi: # name: RaspberryPi @@ -172,7 +176,7 @@ jobs: # run: | # sudo apt-get -y -qq install crossbuild-essential-armhf cmake gettext file ninja-build libc6-armhf-cross qt6-base-dev libqt6serialport6-dev libqt6websockets6-dev libqt6shadertools6-dev qt6-scxml-dev libpcre2-16-0 qt6-declarative-dev # sudo ln -s /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /usr/lib/ld-linux-armhf.so.3 -# +# # - name: Use host Qt tools # shell: bash # run: | diff --git a/.github/workflows/flatpak.yml b/.github/workflows/flatpak.yml index b68545e0c8..05a299ff2b 100644 --- a/.github/workflows/flatpak.yml +++ b/.github/workflows/flatpak.yml @@ -1,6 +1,10 @@ name: Flatpak on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: flatpak: name: "Flatpak" diff --git a/.github/workflows/mac-builds.yaml b/.github/workflows/mac-builds.yaml index a6660fc55b..f59810c7bf 100644 --- a/.github/workflows/mac-builds.yaml +++ b/.github/workflows/mac-builds.yaml @@ -1,12 +1,16 @@ name: macOS build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: brew: # Last X86 macos version supported by GH Actions name: macOS (Release, Brew, Intel) runs-on: macos-13 - + steps: - name: Checkout code uses: actions/checkout@v4 @@ -28,7 +32,7 @@ jobs: brew-m1: name: macOS (Release, Brew, AppleSilicon) runs-on: macos-15 - + steps: - name: Checkout code uses: actions/checkout@v4 @@ -50,7 +54,7 @@ jobs: brew-m1-dev: name: macOS (Dev, Brew, AppleSilicon) runs-on: macos-15 - + steps: - name: Checkout code uses: actions/checkout@v4 @@ -93,7 +97,7 @@ jobs: with: p12-file-base64: ${{ secrets.MAC_CERT_B64 }} p12-password: ${{ secrets.MAC_CERT_PASSWORD }} - + - run: | source ci/osx-package.build.sh env: diff --git a/.github/workflows/nix-builds.yaml b/.github/workflows/nix-builds.yaml index 7f2316bf4e..21005c889b 100644 --- a/.github/workflows/nix-builds.yaml +++ b/.github/workflows/nix-builds.yaml @@ -1,6 +1,10 @@ name: Nix build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: nix: name: Nix diff --git a/.github/workflows/templates.yaml b/.github/workflows/templates.yaml index 74ff78a9b9..728f35421b 100644 --- a/.github/workflows/templates.yaml +++ b/.github/workflows/templates.yaml @@ -1,6 +1,10 @@ name: Template check on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: init_template: name: Template generation diff --git a/.github/workflows/ubuntu-builds.yaml b/.github/workflows/ubuntu-builds.yaml index 3e79ddcda5..7918672b85 100644 --- a/.github/workflows/ubuntu-builds.yaml +++ b/.github/workflows/ubuntu-builds.yaml @@ -1,9 +1,13 @@ name: Ubuntu build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: ubuntu: - name: Ubuntu + name: Ubuntu runs-on: ubuntu-latest strategy: @@ -19,7 +23,7 @@ jobs: container: image: ubuntu:${{ matrix.distro }} - + steps: - name: Install git run: | @@ -49,7 +53,7 @@ jobs: - name: Upload build uses: actions/upload-artifact@v4 - if: matrix.deploy + if: matrix.deploy with: name: ${{ matrix.distro }}-amd64 path: | diff --git a/.github/workflows/wasm.yaml b/.github/workflows/wasm.yaml index d09acca0ab..225bf18762 100644 --- a/.github/workflows/wasm.yaml +++ b/.github/workflows/wasm.yaml @@ -1,6 +1,10 @@ name: WASM on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: wasm: name: WebAssembly diff --git a/.github/workflows/win-builds.yaml b/.github/workflows/win-builds.yaml index 92d43025d1..fb0cf2e76e 100644 --- a/.github/workflows/win-builds.yaml +++ b/.github/workflows/win-builds.yaml @@ -1,6 +1,10 @@ name: Windows build on: [push,pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: winstore: name: Windows (store) diff --git a/3rdparty/avendish b/3rdparty/avendish index b9e9e0feb8..097f24d78c 160000 --- a/3rdparty/avendish +++ b/3rdparty/avendish @@ -1 +1 @@ -Subproject commit b9e9e0feb8ee4efc4a223fb0ed2401d33b18e937 +Subproject commit 097f24d78c9ea5fcc23f8d187bc3cbedfbe5eb74 diff --git a/3rdparty/libossia b/3rdparty/libossia index 6727dcdc63..daaf1dbb12 160000 --- a/3rdparty/libossia +++ b/3rdparty/libossia @@ -1 +1 @@ -Subproject commit 6727dcdc63dc8e881715824a264970dd7676aa4c +Subproject commit daaf1dbb12ed4033d5ef3f573ae0439e8d592d01 diff --git a/3rdparty/mimalloc.cmake b/3rdparty/mimalloc.cmake index 654137e084..6fb94733cf 100644 --- a/3rdparty/mimalloc.cmake +++ b/3rdparty/mimalloc.cmake @@ -1,6 +1,11 @@ if(EMSCRIPTEN) return() endif() + +if(SCORE_HAS_SANITIZERS) + return() +endif() + if(SCORE_USE_SYSTEM_LIBRARIES) find_package(snmalloc GLOBAL CONFIG) else() diff --git a/ci/archlinux-qt6.build.sh b/ci/archlinux-qt6.build.sh index 457d02977a..05e3bc83ab 100755 --- a/ci/archlinux-qt6.build.sh +++ b/ci/archlinux-qt6.build.sh @@ -10,7 +10,8 @@ cmake $SCORE_DIR \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=install \ -DSCORE_DYNAMIC_PLUGINS=1 \ - -DSCORE_PCH=1 + -DSCORE_PCH=1 \ + -DCMAKE_CXX_SCAN_FOR_MODULES=0 cmake --build . -cmake --build . --target install \ No newline at end of file +cmake --build . --target install diff --git a/ci/raspberrypi-aarch64.build.sh b/ci/raspberrypi-aarch64.build.sh index 3d92709a1a..269bd8fc47 100755 --- a/ci/raspberrypi-aarch64.build.sh +++ b/ci/raspberrypi-aarch64.build.sh @@ -19,7 +19,8 @@ cmake $SCORE_DIR \ -DCMAKE_INSTALL_PREFIX=install \ -DLIBREMIDI_NO_PIPEWIRE=1 \ -DSCORE_DISABLED_PLUGINS=score-plugin-jit \ - -DSCORE_LINKER_SCRIPT="$SCORE_DIR/cmake/Deployment/Linux/AppImage/version" + -DSCORE_LINKER_SCRIPT="$SCORE_DIR/cmake/Deployment/Linux/AppImage/version" \ + -DCMAKE_CXX_SCAN_FOR_MODULES=0 cmake --build . cmake --build . --target install/strip diff --git a/ci/wasm.build.sh b/ci/wasm.build.sh index 1f0be1162a..c15af0c02f 100755 --- a/ci/wasm.build.sh +++ b/ci/wasm.build.sh @@ -17,6 +17,7 @@ source /opt/ossia-sdk-wasm/emsdk/emsdk_env.sh -DKFR_ARCH=sse41 \ -DOSSIA_PCH=0 \ -DSCORE_PCH=0 \ + -DCMAKE_CXX_SCAN_FOR_MODULES=0 \ -DOSSIA_SDK=/opt/ossia-sdk-wasm/ \ -DCMAKE_C_FLAGS='-pthread -O3 -ffast-math -msimd128 -msse -msse2 -msse3 -mssse3 -msse4 -msse4.1 -msse4.2 ' \ -DCMAKE_CXX_FLAGS='-DBOOST_ASIO_DISABLE_EPOLL=1 -pthread -O3 -ffast-math -msimd128 -msse -msse2 -msse3 -mssse3 -msse4 -msse4.1 -msse4.2 ' \ diff --git a/cmake/ScoreConfiguration.cmake b/cmake/ScoreConfiguration.cmake index e7dda0e864..b014578a6a 100644 --- a/cmake/ScoreConfiguration.cmake +++ b/cmake/ScoreConfiguration.cmake @@ -220,6 +220,11 @@ if(has_mcx16_flag) add_compile_options(-mcx16) endif() +# Detect usage of asan / ubsan +if("${CMAKE_CXX_FLAGS}" MATCHES ".*sanitize.*") + set(SCORE_HAS_SANITIZERS 1) +endif() + # Commit and version information if(EXISTS "${CMAKE_SOURCE_DIR}/.git") include(GetGitRevisionDescription) diff --git a/src/lib/score/tools/RecursiveWatch.cpp b/src/lib/score/tools/RecursiveWatch.cpp index 4e4f8145ed..598c8931b3 100644 --- a/src/lib/score/tools/RecursiveWatch.cpp +++ b/src/lib/score/tools/RecursiveWatch.cpp @@ -15,7 +15,7 @@ && !defined(_WIN32) \ && !defined(__EMSCRIPTEN__) \ && !defined(__APPLE__) \ - && (!defined(__clang_major__) || (__clang_major__ >= 14 && __clang_major__ < 19)) +&& (!defined(__clang_major__) || __clang_major__ >= 14) #define SCORE_HAS_LLFIO 1 #elif defined(__APPLE__) #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15 diff --git a/src/plugins/score-plugin-avnd/AvndProcesses/DeviceRecorder.hpp b/src/plugins/score-plugin-avnd/AvndProcesses/DeviceRecorder.hpp index c01c144996..7e9d367c40 100644 --- a/src/plugins/score-plugin-avnd/AvndProcesses/DeviceRecorder.hpp +++ b/src/plugins/score-plugin-avnd/AvndProcesses/DeviceRecorder.hpp @@ -914,8 +914,8 @@ struct DeviceRecorder : PatternObject if(!std::exchange(started, true)) { inputs.pattern.reprocess(); - worker.request(std::make_unique( - record_impl, play_impl, inputs.filename, roots, inputs.timestamped)); + worker.request(std::unique_ptr(new reset_message{ + record_impl, play_impl, inputs.filename, roots, inputs.timestamped})); } switch(inputs.mode) diff --git a/src/plugins/score-plugin-avnd/AvndProcesses/Teleplot.hpp b/src/plugins/score-plugin-avnd/AvndProcesses/Teleplot.hpp index cbeca26fb6..b509bdc41e 100644 --- a/src/plugins/score-plugin-avnd/AvndProcesses/Teleplot.hpp +++ b/src/plugins/score-plugin-avnd/AvndProcesses/Teleplot.hpp @@ -92,7 +92,7 @@ struct Teleplot : PatternObject if(!ip.empty() && port > 1) { socket = std::make_shared( - ossia::net::send_socket_configuration{{.host = ip, .port = port}}, + ossia::net::outbound_socket_configuration{.host = ip, .port = port}, *io_context); socket->connect(); } @@ -201,7 +201,7 @@ struct Teleplot : PatternObject if(!socket) { socket = std::make_shared( - ossia::net::send_socket_configuration{{.host = "127.0.0.1", .port = 47269}}, + ossia::net::outbound_socket_configuration{.host = "127.0.0.1", .port = 47269}, *io_context); socket->connect(); } diff --git a/src/plugins/score-plugin-protocols/Protocols/Artnet/ArtnetDevice.cpp b/src/plugins/score-plugin-protocols/Protocols/Artnet/ArtnetDevice.cpp index e458b34040..fd56e14dc5 100644 --- a/src/plugins/score-plugin-protocols/Protocols/Artnet/ArtnetDevice.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/Artnet/ArtnetDevice.cpp @@ -238,16 +238,25 @@ bool ArtnetDevice::reconnect() if(host.empty()) host = "0.0.0.0"; - ossia::net::socket_configuration sock_conf; - sock_conf.host = host; - sock_conf.port = ossia::net::e131_protocol::default_port; - if(set.mode == ArtnetSpecificSettings::Source) + { + ossia::net::outbound_socket_configuration sock_conf; + sock_conf.host = host; + sock_conf.port = ossia::net::e131_protocol::default_port; + artnet_proto = std::make_unique(m_ctx, conf, sock_conf); + } else + { + ossia::net::inbound_socket_configuration sock_conf; + sock_conf.bind = host; + sock_conf.port = ossia::net::e131_protocol::default_port; + artnet_proto = std::make_unique( m_ctx, conf, sock_conf); + } + break; } case ArtnetSpecificSettings::DMXUSBPRO: diff --git a/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolFactory.cpp b/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolFactory.cpp index bb60871150..43eb84e7f5 100644 --- a/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolFactory.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolFactory.cpp @@ -91,7 +91,7 @@ class CoAPTCPEnumerator final : public DNSSDEnumerator set.protocol = CoAPProtocolFactory::static_concreteKey(); CoAPSpecificSettings sub; - ossia::net::tcp_configuration conf; + ossia::net::tcp_client_configuration conf; conf.host = ip.toStdString(); conf.port = port.toInt(); sub.configuration.transport = conf; @@ -129,7 +129,7 @@ const Device::DeviceSettings& CoAPProtocolFactory::defaultSettings() const noexc CoAPSpecificSettings specif; specif.configuration.transport = ossia::net::udp_configuration{ {.local = {}, - .remote = ossia::net::send_socket_configuration{"127.0.0.1", 5683}}}; + .remote = ossia::net::outbound_socket_configuration{"127.0.0.1", 5683}}}; s.deviceSpecificSettings = QVariant::fromValue(specif); return s; }(); diff --git a/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolSettingsWidget.cpp b/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolSettingsWidget.cpp index 7169d76353..c9a3ecd6c9 100644 --- a/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolSettingsWidget.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/CoAP/CoAPProtocolSettingsWidget.cpp @@ -104,7 +104,7 @@ CoAPTransportWidget::setConfiguration(const ossia::net::coap_client_configuratio self.m_udp->setSettings(conf); proto = CoapProtocol::UDP; } - void operator()(const ossia::net::tcp_configuration& conf) + void operator()(const ossia::net::tcp_client_configuration& conf) { self.m_tcp->setSettings(conf); proto = CoapProtocol::TCP; diff --git a/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.cpp b/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.cpp index 5933404828..483e6acaa2 100644 --- a/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.cpp @@ -104,6 +104,7 @@ class DNSSDWorker killTimer(m_timer); m_serv.removeListener(this); m_serv.endBrowsing(); + this->deleteLater(); } void timerEvent(QTimerEvent* ev) override { m_serv.browse(10); } @@ -124,8 +125,11 @@ W_OBJECT_IMPL(Protocols::DNSSDWorker) namespace Protocols { +QThread DNSSDEnumerator::g_dnssd_worker_thread; DNSSDEnumerator::DNSSDEnumerator(const std::string& service) { + g_dnssd_worker_thread.setObjectName("Foo"); + g_dnssd_worker_thread.start(); m_worker = new DNSSDWorker{service}; } @@ -133,11 +137,9 @@ DNSSDEnumerator::~DNSSDEnumerator() { } void DNSSDEnumerator::start() { - m_worker->moveToThread(&m_workerThread); - connect(&m_workerThread, &QThread::finished, m_worker, &QObject::deleteLater); + m_worker->moveToThread(&g_dnssd_worker_thread); connect(m_worker, &DNSSDWorker::on_newHost, this, &DNSSDEnumerator::addNewDevice); connect(m_worker, &DNSSDWorker::on_removedHost, this, &DNSSDEnumerator::deviceRemoved); - m_workerThread.start(); QMetaObject::invokeMethod(m_worker, &DNSSDWorker::start, Qt::QueuedConnection); } @@ -145,8 +147,6 @@ void DNSSDEnumerator::start() void DNSSDEnumerator::stop() { QMetaObject::invokeMethod(m_worker, &DNSSDWorker::stop, Qt::QueuedConnection); - m_workerThread.quit(); - m_workerThread.wait(); } void DNSSDEnumerator::enumerate( diff --git a/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.hpp b/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.hpp index a69e19db93..ab95fb393c 100644 --- a/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/DNSSDDeviceEnumerator.hpp @@ -36,7 +36,8 @@ class DNSSDEnumerator : public Device::DeviceEnumerator protected: private: DNSSDWorker* m_worker{}; - QThread m_workerThread; + // Avahi only supports being called from *one* thread across an entire execution. + static QThread g_dnssd_worker_thread; }; #endif } diff --git a/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolFactory.cpp b/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolFactory.cpp index 3f2f345a2d..b072695071 100644 --- a/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolFactory.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolFactory.cpp @@ -44,7 +44,7 @@ QString MQTTProtocolFactory::category() const noexcept static ossia::net::mqtt5_configuration defaultMQTTConfig() noexcept { ossia::net::mqtt5_configuration config; - config.transport = ossia::net::tcp_configuration{{.host = "127.0.0.1", .port = 1883}}; + config.transport = ossia::net::tcp_client_configuration{{.host = "127.0.0.1", .port = 1883}}; return config; } @@ -90,7 +90,7 @@ class MQTTTCPEnumerator final : public DNSSDEnumerator set.protocol = MQTTProtocolFactory::static_concreteKey(); MQTTSpecificSettings sub; - ossia::net::tcp_configuration conf; + ossia::net::tcp_client_configuration conf; conf.host = ip.toStdString(); conf.port = port.toInt(); sub.configuration.transport = conf; @@ -127,7 +127,7 @@ const Device::DeviceSettings& MQTTProtocolFactory::defaultSettings() const noexc s.protocol = concreteKey(); s.name = "MQTT"; MQTTSpecificSettings specif; - specif.configuration.transport = ossia::net::tcp_configuration{"127.0.0.1", 1883}; + specif.configuration.transport = ossia::net::tcp_client_configuration{"127.0.0.1", 1883}; s.deviceSpecificSettings = QVariant::fromValue(specif); return s; }(); diff --git a/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolSettingsWidget.cpp b/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolSettingsWidget.cpp index c57bbe2fc4..eab75856ff 100644 --- a/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolSettingsWidget.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/MQTT/MQTTProtocolSettingsWidget.cpp @@ -91,7 +91,7 @@ MQTTTransportWidget::setConfiguration(const ossia::net::mqtt5_configuration& osc MQTTTransportWidget& self; const ossia::net::mqtt5_configuration& osc_conf; MqttProtocol proto{}; - void operator()(const ossia::net::tcp_configuration& conf) + void operator()(const ossia::net::tcp_client_configuration& conf) { self.m_tcp->setSettings(conf); proto = MqttProtocol::TCP; diff --git a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/Serialization.hpp b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/Serialization.hpp index 990ab9a269..395e3bcefd 100644 --- a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/Serialization.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/Serialization.hpp @@ -5,7 +5,9 @@ #include JSON_METADATA(ossia::net::udp_configuration, "UDP") -JSON_METADATA(ossia::net::tcp_configuration, "TCP") +JSON_METADATA(ossia::net::udp_server_configuration, "UDPServer") +JSON_METADATA(ossia::net::tcp_client_configuration, "TCP") +JSON_METADATA(ossia::net::tcp_server_configuration, "TCPServer") JSON_METADATA(ossia::net::unix_dgram_configuration, "UnixDatagram") JSON_METADATA(ossia::net::unix_stream_configuration, "UnixStream") JSON_METADATA(ossia::net::serial_configuration, "Serial") diff --git a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPServerWidget.hpp b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPServerWidget.hpp new file mode 100644 index 0000000000..c5f8e90cea --- /dev/null +++ b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPServerWidget.hpp @@ -0,0 +1,60 @@ +#pragma once +#include + +#include + +#include + +#include +#include +#include +namespace Protocols +{ + +class TCPServerWidget : public QWidget +{ +public: + TCPServerWidget(Device::ProtocolSettingsWidget& proto, QWidget* parent) + : QWidget{parent} + { + auto layout = new QFormLayout{this}; + layout->setContentsMargins(0, 0, 0, 0); + + m_remotePort = new QSpinBox(this); + m_remotePort->setRange(0, 65535); + m_remotePort->setValue(9996); + proto.checkForChanges(m_remotePort); + + m_framing = new QComboBox{this}; + m_framing->addItems({"Size prefixing", "SLIP"}); + m_framing->setCurrentIndex(1); + + layout->addRow(tr("Port"), m_remotePort); + layout->addRow(tr("Framing"), m_framing); + } + + framing_type framing() const noexcept + { + return (framing_type)m_framing->currentIndex(); + } + + ossia::net::tcp_server_configuration settings() const noexcept + { + ossia::net::tcp_server_configuration conf; + conf.port = m_remotePort->value(); + return conf; + } + + void setSettings( + const ossia::net::osc_protocol_configuration& c, + const ossia::net::tcp_server_configuration& conf) + { + m_remotePort->setValue(conf.port); + m_framing->setCurrentIndex(c.framing); + } + +private: + QSpinBox* m_remotePort{}; + QComboBox* m_framing{}; +}; +} diff --git a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPWidget.hpp b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPWidget.hpp index b455611a15..689fc0e099 100644 --- a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPWidget.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/TCPWidget.hpp @@ -26,6 +26,7 @@ class BasicTCPWidget : public QWidget m_remotePort->setValue(9996); m_remotePort->setWhatsThis( tr("This is the communication port used for the TCP connection.")); + proto.checkForChanges(m_remotePort); m_host = new QLineEdit(this); m_host->setText("127.0.0.1"); @@ -38,15 +39,15 @@ class BasicTCPWidget : public QWidget layout->addRow(tr("Host"), m_host); } - ossia::net::tcp_configuration settings() const noexcept + ossia::net::tcp_client_configuration settings() const noexcept { - ossia::net::tcp_configuration conf; + ossia::net::tcp_client_configuration conf; conf.port = m_remotePort->value(); conf.host = m_host->text().toStdString(); return conf; } - void setSettings(const ossia::net::tcp_configuration& conf) + void setSettings(const ossia::net::tcp_client_configuration& conf) { m_remotePort->setValue(conf.port); m_host->setText(QString::fromStdString(conf.host)); @@ -71,6 +72,7 @@ class TCPWidget : public QWidget m_remotePort->setValue(9996); m_remotePort->setWhatsThis( tr("This is the communication port used for the TCP connection.")); + proto.checkForChanges(m_remotePort); m_host = new QLineEdit(this); m_host->setText("127.0.0.1"); @@ -93,9 +95,9 @@ class TCPWidget : public QWidget return (framing_type)m_framing->currentIndex(); } - ossia::net::tcp_configuration settings() const noexcept + ossia::net::tcp_client_configuration settings() const noexcept { - ossia::net::tcp_configuration conf; + ossia::net::tcp_client_configuration conf; conf.port = m_remotePort->value(); conf.host = m_host->text().toStdString(); return conf; @@ -103,7 +105,7 @@ class TCPWidget : public QWidget void setSettings( const ossia::net::osc_protocol_configuration& c, - const ossia::net::tcp_configuration& conf) + const ossia::net::tcp_client_configuration& conf) { m_remotePort->setValue(conf.port); m_framing->setCurrentIndex(c.framing); diff --git a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/UDPWidget.hpp b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/UDPWidget.hpp index 58714b654c..af8c155d77 100644 --- a/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/UDPWidget.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/NetworkWidgets/UDPWidget.hpp @@ -58,9 +58,9 @@ class UDPWidget : public QWidget ossia::net::udp_configuration settings() const noexcept { ossia::net::udp_configuration conf; - conf.local = ossia::net::receive_socket_configuration{ + conf.local = ossia::net::inbound_socket_configuration{ "0.0.0.0", (uint16_t)m_localPort->value()}; - conf.remote = ossia::net::send_socket_configuration{ + conf.remote = ossia::net::outbound_socket_configuration{ m_host->text().toStdString(), (uint16_t)m_remotePort->value(), m_broadcast->isChecked()}; return conf; diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.cpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.cpp index 7901d4f25f..ede7d04caa 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.cpp @@ -15,8 +15,10 @@ #include #include +#include #include #include +#include #include @@ -32,6 +34,107 @@ OSCDevice::OSCDevice( m_capas.hasCallbacks = false; } +void OSCDevice::disconnect() +{ + m_oscproto = nullptr; + m_zeroconf = {}; + Device::OwningDeviceInterface::disconnect(); +} + +struct osc_protocols +{ + std::unique_ptr ret; + ossia::net::multiplex_protocol* multiplex{}; + ossia::oscquery_asio::oscquery_server_protocol_base* oscquery{}; + ossia::net::osc_protocol_base* osc{}; + ossia::net::rate_limiting_protocol* ratelimit{}; +}; + +struct convert_osc_transport_to_server +{ + using ret = std::optional; + ret operator()(const ossia::net::udp_configuration& conf) + { + if(conf.local) + return ossia::net::udp_server_configuration{*conf.local}; + return std::nullopt; + } + ret operator()(const ossia::net::unix_dgram_configuration& conf) + { + if(conf.local) + return ossia::net::unix_dgram_server_configuration{*conf.local}; + return std::nullopt; + } + ret operator()(const ossia::net::unix_stream_configuration& conf) + { + return std::nullopt; + } + ret operator()(const ossia::net::serial_configuration& conf) { return conf; } + ret operator()(const ossia::net::tcp_server_configuration& conf) { return conf; } + ret operator()(const ossia::net::ws_server_configuration& conf) { return conf; } + ret operator()(const ossia::net::tcp_client_configuration& conf) + { + return std::nullopt; + } + ret operator()(const ossia::net::ws_client_configuration& conf) + { + return std::nullopt; + } + + ret operator()(const auto& conf) { return conf; } +}; +osc_protocols make_osc_protocol( + const ossia::net::network_context_ptr& m_ctx, const OSCSpecificSettings& stgs) +{ + osc_protocols protos; + if(stgs.oscquery) + { + auto multiplex = std::make_unique(); + protos.multiplex = multiplex.get(); + + if(auto proto = ossia::net::make_osc_protocol(m_ctx, stgs.configuration)) + { + protos.osc = proto.get(); + multiplex->expose_to(std::move(proto)); + } + else + return {}; + + std::vector conf; + + ossia::visit([&](const auto& elt) { + if(auto t = convert_osc_transport_to_server{}(elt)) + conf.push_back(std::move(*t)); + }, stgs.configuration.transport); + + if(auto proto + = std::make_unique( + m_ctx, conf, *stgs.oscquery, false)) + { + protos.oscquery = proto.get(); + multiplex->expose_to(std::move(proto)); + } + protos.ret = std::move(multiplex); + } + else if(auto proto = ossia::net::make_osc_protocol(m_ctx, stgs.configuration)) + { + protos.osc = proto.get(); + protos.ret = std::move(proto); + } + + if(!protos.ret || !protos.osc) + return {}; + + if(stgs.rate) + { + auto rl = std::make_unique( + std::chrono::milliseconds{*stgs.rate}, std::move(protos.ret)); + protos.ratelimit = rl.get(); + protos.ret = std::move(rl); + } + return protos; +} + bool OSCDevice::reconnect() { disconnect(); @@ -41,44 +144,15 @@ bool OSCDevice::reconnect() const OSCSpecificSettings& stgs = settings().deviceSpecificSettings.value(); const auto& name = settings().name.toStdString(); - if(auto proto = ossia::net::make_osc_protocol(m_ctx, stgs.configuration)) + auto protos = make_osc_protocol(m_ctx, stgs); + if(protos.ret) { - if(stgs.rate) - { - auto rate = std::make_unique( - std::chrono::milliseconds{*stgs.rate}, std::move(proto)); - m_dev = std::make_unique(std::move(rate), name); - } - else - { - m_dev = std::make_unique(std::move(proto), name); - } + m_dev = std::make_unique(std::move(protos.ret), name); + m_oscproto = protos.osc; if(m_dev) { - if(stgs.bonjour) - { - if(auto udp = ossia_variant_alias::get_if( - &stgs.configuration.transport)) - { - m_zeroconf = ossia::net::make_zeroconf_server( - name, "_osc._udp", "", udp->local->port, 0); - } - else if( - auto tcp = ossia_variant_alias::get_if( - &stgs.configuration.transport)) - { - m_zeroconf - = ossia::net::make_zeroconf_server(name, "_osc._tcp", "", tcp->port, 0); - } - else if( - auto ws = ossia_variant_alias::get_if( - &stgs.configuration.transport)) - { - m_zeroconf - = ossia::net::make_zeroconf_server(name, "_osc._ws", "", ws->port, 0); - } - } + setup_zeroconf(stgs, name); } deviceChanged(nullptr, m_dev.get()); setLogging_impl(Device::get_cur_logging(isLogging())); @@ -110,15 +184,18 @@ void OSCDevice::recreate(const Device::Node& n) bool OSCDevice::isLearning() const { - auto& proto = static_cast(m_dev->get_protocol()); - return proto.learning(); + if(auto proto = m_oscproto) + return proto->learning(); + return false; } void OSCDevice::setLearning(bool b) { if(!m_dev) return; - auto& proto = static_cast(m_dev->get_protocol()); + if(!m_oscproto) + return; + auto& proto = *m_oscproto; auto& dev = *m_dev; if(b) { @@ -146,4 +223,29 @@ void OSCDevice::setLearning(bool b) proto.set_learning(b); } + +void OSCDevice::setup_zeroconf(const OSCSpecificSettings& stgs, const std::string& name) +{ + if(stgs.bonjour) + { + if(auto udp = ossia_variant_alias::get_if( + &stgs.configuration.transport)) + { + m_zeroconf + = ossia::net::make_zeroconf_server(name, "_osc._udp", "", udp->local->port, 0); + } + else if( + auto tcp = ossia_variant_alias::get_if( + &stgs.configuration.transport)) + { + m_zeroconf = ossia::net::make_zeroconf_server(name, "_osc._tcp", "", tcp->port, 0); + } + else if( + auto ws = ossia_variant_alias::get_if( + &stgs.configuration.transport)) + { + m_zeroconf = ossia::net::make_zeroconf_server(name, "_osc._ws", "", ws->port, 0); + } + } +} } diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.hpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.hpp index 1b09000276..e88d4c7392 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCDevice.hpp @@ -3,14 +3,24 @@ #include +namespace ossia::net +{ +class protocol_base; +template +class can_learn; +using osc_protocol_base = can_learn; +} + namespace Protocols { +struct OSCSpecificSettings; class OSCDevice final : public Device::OwningDeviceInterface { public: OSCDevice( const Device::DeviceSettings& stngs, const ossia::net::network_context_ptr& ctx); + void disconnect() override; bool reconnect() override; void recreate(const Device::Node&) final override; @@ -18,7 +28,9 @@ class OSCDevice final : public Device::OwningDeviceInterface void setLearning(bool) final override; private: + void setup_zeroconf(const OSCSpecificSettings& stgs, const std::string& name); const ossia::net::network_context_ptr& m_ctx; ossia::net::zeroconf_server m_zeroconf{}; + ossia::net::osc_protocol_base* m_oscproto{}; }; } diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolFactory.cpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolFactory.cpp index 2db9a4e365..de424f0fe8 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolFactory.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolFactory.cpp @@ -45,8 +45,8 @@ static ossia::net::osc_protocol_configuration defaultOSCConfig() noexcept config.mode = ossia::net::osc_protocol_configuration::MIRROR; config.version = ossia::net::osc_protocol_configuration::OSC1_0; ossia::net::udp_configuration udp; - udp.local = ossia::net::receive_socket_configuration{"0.0.0.0", 9996}; - udp.remote = ossia::net::send_socket_configuration{"127.0.0.1", 9997}; + udp.local = ossia::net::inbound_socket_configuration{"0.0.0.0", 9996}; + udp.remote = ossia::net::outbound_socket_configuration{"127.0.0.1", 9997}; config.transport = udp; return config; } @@ -106,8 +106,8 @@ struct OSCCompatibleCheck return true; } bool operator()( - const ossia::net::tcp_configuration& lhs, - const ossia::net::tcp_configuration& rhs) const noexcept + const ossia::net::tcp_client_configuration& lhs, + const ossia::net::tcp_client_configuration& rhs) const noexcept { if(config1.mode == ossia::net::osc_protocol_configuration::HOST && config2.mode == ossia::net::osc_protocol_configuration::HOST @@ -126,7 +126,7 @@ struct OSCCompatibleCheck return true; } bool operator()( - const ossia::net::tcp_configuration& lhs, + const ossia::net::tcp_client_configuration& lhs, const ossia::net::ws_server_configuration& rhs) const noexcept { if(config1.mode == ossia::net::osc_protocol_configuration::HOST @@ -137,7 +137,7 @@ struct OSCCompatibleCheck } bool operator()( const ossia::net::ws_server_configuration& lhs, - const ossia::net::tcp_configuration& rhs) const noexcept + const ossia::net::tcp_client_configuration& rhs) const noexcept { if(config1.mode == ossia::net::osc_protocol_configuration::HOST && config2.mode == ossia::net::osc_protocol_configuration::HOST @@ -185,7 +185,7 @@ class OSCTCPEnumerator final : public DNSSDEnumerator set.protocol = OSCProtocolFactory::static_concreteKey(); OSCSpecificSettings sub; - ossia::net::tcp_configuration conf; + ossia::net::tcp_client_configuration conf; conf.host = ip.toStdString(); conf.port = port.toInt(); sub.configuration.transport = conf; @@ -219,8 +219,8 @@ class OSCUDPEnumerator final : public DNSSDEnumerator OSCSpecificSettings sub; ossia::net::udp_configuration udp; - udp.local = ossia::net::receive_socket_configuration{"0.0.0.0", 9996}; - udp.remote = ossia::net::send_socket_configuration{ + udp.local = ossia::net::inbound_socket_configuration{"0.0.0.0", 9996}; + udp.remote = ossia::net::outbound_socket_configuration{ ip.toStdString(), uint16_t(port.toInt())}; sub.configuration.transport = udp; @@ -241,8 +241,8 @@ OSCProtocolFactory::getEnumerators(const score::DocumentContext& ctx) const auto copy = arr; copy.detach(); - return QVariant::fromValue( - OSCSpecificSettings{readOSCConfig(copy), std::nullopt, false, std::move(copy)}); + return QVariant::fromValue(OSCSpecificSettings{ + readOSCConfig(copy), std::nullopt, false, {}, std::move(copy)}); }, ctx}; diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.cpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.cpp index ffbd5282ac..153c3073cf 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,9 @@ OSCTransportWidget::OSCTransportWidget( m_tcp = new TCPWidget{proto, this}; m_transportLayout->addWidget(m_tcp); + m_tcp_server = new TCPServerWidget{proto, this}; + m_transportLayout->addWidget(m_tcp_server); + m_serial = new SerialWidget{proto, this}; m_transportLayout->addWidget(m_serial); @@ -81,12 +85,18 @@ OSCProtocolSettingsWidget::OSCProtocolSettingsWidget(QWidget* parent) m_transport = new QComboBox{this}; m_transport->addItems( {"UDP", "TCP", "Serial port", "Unix Datagram", "Unix Stream", "Websocket Client", - "Websocket Server"}); + "Websocket Server", "TCP Server"}); checkForChanges(m_transport); m_oscVersion = new QComboBox{this}; m_oscVersion->addItems({"1.0", "1.1", "Extended"}); + m_oscquery = new QSpinBox{this}; + m_oscquery->setWhatsThis(tr("Expose OSC device over OSCQuery if port is not 0")); + m_oscquery->setRange(0, 65535); + m_oscquery->setValue(0); + checkForChanges(m_oscquery); + m_transportWidget = new OSCTransportWidget{*this, this}; QObject::connect( m_transport, qOverload(&QComboBox::currentIndexChanged), this, @@ -96,6 +106,7 @@ OSCProtocolSettingsWidget::OSCProtocolSettingsWidget(QWidget* parent) layout->addRow(tr("Name"), m_deviceNameEdit); layout->addRow(tr("Rate limit"), m_rate); layout->addRow(tr("Bonjour"), m_bonjour); + layout->addRow(tr("OSCQuery"), m_oscquery); layout->addRow(tr("OSC Version"), m_oscVersion); layout->addRow(tr("Protocol"), m_transport); layout->addRow(m_transportWidget); @@ -116,6 +127,11 @@ OSCTransportWidget::configuration(OscProtocol index) const noexcept conf.framing = m_tcp->framing(); conf.mode = ossia::net::osc_protocol_configuration::MIRROR; break; + case OscProtocol::TCPServer: + conf.transport = m_tcp_server->settings(); + conf.framing = m_tcp_server->framing(); + conf.mode = ossia::net::osc_protocol_configuration::HOST; + break; case OscProtocol::Serial: conf.transport = m_serial->settings(); conf.framing = m_serial->framing(); @@ -155,11 +171,16 @@ OscProtocol OSCTransportWidget::setConfiguration( self.m_udp->setSettings(conf); proto = OscProtocol::UDP; } - void operator()(const ossia::net::tcp_configuration& conf) + void operator()(const ossia::net::tcp_client_configuration& conf) { self.m_tcp->setSettings(osc_conf, conf); proto = OscProtocol::TCP; } + void operator()(const ossia::net::tcp_server_configuration& conf) + { + self.m_tcp_server->setSettings(osc_conf, conf); + proto = OscProtocol::TCPServer; + } void operator()(const ossia::net::unix_dgram_configuration& conf) { self.m_unix_dgram->setSettings(conf); @@ -205,6 +226,9 @@ Device::DeviceSettings OSCProtocolSettingsWidget::getSettings() const osc.configuration.version = static_cast(m_oscVersion->currentIndex()); osc.rate = m_rate->rate(); osc.bonjour = m_bonjour->isChecked(); + osc.oscquery = m_oscquery->value(); + if(osc.oscquery.value() <= 0) + osc.oscquery.reset(); osc.jsonToLoad.clear(); // TODO list.append(m_namespaceFilePathEdit->text()); @@ -244,6 +268,8 @@ void OSCProtocolSettingsWidget::setSettings(const Device::DeviceSettings& settin m_oscVersion->setCurrentIndex(m_settings.configuration.version); m_rate->setRate(m_settings.rate); m_bonjour->setChecked(m_settings.bonjour); + if(m_settings.oscquery) + m_oscquery->setValue(*m_settings.oscquery); auto proto = m_transportWidget->setConfiguration(m_settings.configuration); m_transport->setCurrentIndex((int)proto); } diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.hpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.hpp index 8046091e9a..9f6ca9cff1 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCProtocolSettingsWidget.hpp @@ -17,6 +17,7 @@ namespace Protocols class UDPWidget; class TCPWidget; +class TCPServerWidget; class UnixDatagramWidget; class UnixStreamWidget; class SerialWidget; @@ -33,7 +34,8 @@ enum class OscProtocol UnixDatagram = 3, UnixStream = 4, WSClient = 5, - WSServer = 6 + WSServer = 6, + TCPServer = 7 }; class OSCTransportWidget : public QWidget @@ -51,6 +53,7 @@ class OSCTransportWidget : public QWidget UDPWidget* m_udp{}; TCPWidget* m_tcp{}; + TCPServerWidget* m_tcp_server{}; SerialWidget* m_serial{}; UnixDatagramWidget* m_unix_dgram{}; UnixStreamWidget* m_unix_stream{}; @@ -76,6 +79,7 @@ class OSCProtocolSettingsWidget final : public Device::ProtocolSettingsWidget QCheckBox* m_bonjour{}; QComboBox* m_transport{}; QComboBox* m_oscVersion{}; + QSpinBox* m_oscquery{}; OSCTransportWidget* m_transportWidget{}; OSCSpecificSettings m_settings; }; diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettings.hpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettings.hpp index 0ec21f341f..004d176049 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettings.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettings.hpp @@ -13,6 +13,7 @@ struct OSCSpecificSettings ossia::net::osc_protocol_configuration configuration; std::optional rate{}; bool bonjour{}; + std::optional oscquery{}; // Note: this one is not saved, it is only used // to allow loading a .json file as an OSC device diff --git a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettingsSerialization.cpp b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettingsSerialization.cpp index 224356e639..64555aac2b 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettingsSerialization.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSC/OSCSpecificSettingsSerialization.cpp @@ -9,21 +9,21 @@ #include template <> -void DataStreamReader::read(const ossia::net::socket_configuration& n) +void DataStreamReader::read(const ossia::net::outbound_socket_configuration& n) { m_stream << n.host << n.port << n.broadcast; insertDelimiter(); } template <> -void DataStreamWriter::write(ossia::net::socket_configuration& n) +void DataStreamWriter::write(ossia::net::outbound_socket_configuration& n) { m_stream >> n.host >> n.port >> n.broadcast; checkDelimiter(); } template <> -void JSONReader::read(const ossia::net::socket_configuration& n) +void JSONReader::read(const ossia::net::outbound_socket_configuration& n) { stream.StartObject(); obj["Host"] = n.host; @@ -33,7 +33,7 @@ void JSONReader::read(const ossia::net::socket_configuration& n) } template <> -void JSONWriter::write(ossia::net::socket_configuration& n) +void JSONWriter::write(ossia::net::outbound_socket_configuration& n) { n.host = obj["Host"].toStdString(); n.port = obj["Port"].toInt(); @@ -41,6 +41,39 @@ void JSONWriter::write(ossia::net::socket_configuration& n) n.broadcast = bc->toBool(); } +template <> +void DataStreamReader::read(const ossia::net::inbound_socket_configuration& n) +{ + m_stream << n.bind << n.port; + insertDelimiter(); +} + +template <> +void DataStreamWriter::write(ossia::net::inbound_socket_configuration& n) +{ + m_stream >> n.bind >> n.port; + checkDelimiter(); +} + +template <> +void JSONReader::read(const ossia::net::inbound_socket_configuration& n) +{ + stream.StartObject(); + obj["Bind"] = n.bind; + obj["Port"] = (int)n.port; + stream.EndObject(); +} + +template <> +void JSONWriter::write(ossia::net::inbound_socket_configuration& n) +{ + if(auto b = obj.tryGet("Bind")) + n.bind = b->toStdString(); + else if(auto h = obj.tryGet("Host")) + n.bind = h->toStdString(); + n.port = obj["Port"].toInt(); +} + template <> void DataStreamReader::read(const ossia::net::fd_configuration& n) { @@ -165,54 +198,6 @@ void JSONWriter::write(ossia::net::serial_configuration& n) n.stop_bits <<= obj["StopBits"]; } -template <> -void DataStreamReader::read(const ossia::net::receive_socket_configuration& n) -{ - read((ossia::net::socket_configuration&)n); -} - -template <> -void DataStreamWriter::write(ossia::net::receive_socket_configuration& n) -{ - write((ossia::net::socket_configuration&)n); -} - -template <> -void JSONReader::read(const ossia::net::receive_socket_configuration& n) -{ - read((ossia::net::socket_configuration&)n); -} - -template <> -void JSONWriter::write(ossia::net::receive_socket_configuration& n) -{ - write((ossia::net::socket_configuration&)n); -} - -template <> -void DataStreamReader::read(const ossia::net::send_socket_configuration& n) -{ - read((ossia::net::socket_configuration&)n); -} - -template <> -void DataStreamWriter::write(ossia::net::send_socket_configuration& n) -{ - write((ossia::net::socket_configuration&)n); -} - -template <> -void JSONReader::read(const ossia::net::send_socket_configuration& n) -{ - read((ossia::net::socket_configuration&)n); -} - -template <> -void JSONWriter::write(ossia::net::send_socket_configuration& n) -{ - write((ossia::net::socket_configuration&)n); -} - template <> void DataStreamReader::read(const ossia::net::receive_fd_configuration& n) { @@ -286,27 +271,51 @@ void JSONWriter::write(ossia::net::unix_stream_configuration& n) } template <> -void DataStreamReader::read(const ossia::net::tcp_configuration& n) +void DataStreamReader::read(const ossia::net::tcp_client_configuration& n) { - read((ossia::net::socket_configuration&)n); + read((ossia::net::outbound_socket_configuration&)n); } template <> -void DataStreamWriter::write(ossia::net::tcp_configuration& n) +void DataStreamWriter::write(ossia::net::tcp_client_configuration& n) { - write((ossia::net::socket_configuration&)n); + write((ossia::net::outbound_socket_configuration&)n); } template <> -void JSONReader::read(const ossia::net::tcp_configuration& n) +void JSONReader::read(const ossia::net::tcp_client_configuration& n) { - read((ossia::net::socket_configuration&)n); + read((ossia::net::outbound_socket_configuration&)n); } template <> -void JSONWriter::write(ossia::net::tcp_configuration& n) +void JSONWriter::write(ossia::net::tcp_client_configuration& n) { - write((ossia::net::socket_configuration&)n); + write((ossia::net::outbound_socket_configuration&)n); +} + +template <> +void DataStreamReader::read(const ossia::net::tcp_server_configuration& n) +{ + read((ossia::net::inbound_socket_configuration&)n); +} + +template <> +void DataStreamWriter::write(ossia::net::tcp_server_configuration& n) +{ + write((ossia::net::inbound_socket_configuration&)n); +} + +template <> +void JSONReader::read(const ossia::net::tcp_server_configuration& n) +{ + read((ossia::net::inbound_socket_configuration&)n); +} + +template <> +void JSONWriter::write(ossia::net::tcp_server_configuration& n) +{ + write((ossia::net::inbound_socket_configuration&)n); } template <> @@ -408,14 +417,14 @@ void DataStreamReader::read(const Protocols::OSCSpecificSettings& n) { // TODO put it in the right order before 1.0 final. // TODO same for minuit, etc.. - m_stream << n.configuration << n.rate << n.bonjour << n.jsonToLoad; + m_stream << n.configuration << n.rate << n.bonjour << n.jsonToLoad << n.oscquery; insertDelimiter(); } template <> void DataStreamWriter::write(Protocols::OSCSpecificSettings& n) { - m_stream >> n.configuration >> n.rate >> n.bonjour >> n.jsonToLoad; + m_stream >> n.configuration >> n.rate >> n.bonjour >> n.jsonToLoad >> n.oscquery; checkDelimiter(); } @@ -427,6 +436,8 @@ void JSONReader::read(const Protocols::OSCSpecificSettings& n) obj["Rate"] = *n.rate; if(n.bonjour) obj["Bonjour"] = true; + if(n.oscquery) + obj["OSCQuery"] = *n.oscquery; } template <> @@ -436,9 +447,9 @@ void JSONWriter::write(Protocols::OSCSpecificSettings& n) if(auto outputPort = obj.tryGet("OutputPort")) { ossia::net::udp_configuration conf; - conf.local = ossia::net::receive_socket_configuration{ + conf.local = ossia::net::inbound_socket_configuration{ "0.0.0.0", (uint16_t)obj["OutputPort"].toInt()}; - conf.remote = ossia::net::send_socket_configuration{ + conf.remote = ossia::net::outbound_socket_configuration{ obj["Host"].toStdString(), (uint16_t)obj["InputPort"].toInt()}; n.configuration.mode = ossia::net::osc_protocol_configuration::MIRROR; n.configuration.version = ossia::net::osc_protocol_configuration::OSC1_0; @@ -453,4 +464,7 @@ void JSONWriter::write(Protocols::OSCSpecificSettings& n) n.rate = it->toInt(); assign_with_default(n.bonjour, obj.tryGet("Bonjour"), false); + + if(auto it = obj.tryGet("OSCQuery")) + n.oscquery = it->toInt(); } diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.cpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.cpp index 538a788323..790730c1fe 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -31,29 +32,29 @@ #include W_OBJECT_IMPL(Protocols::OSCQueryDevice) -bool resolve_ip(std::string host) +static bool resolve_ip(const std::string& host) { try { - std::string m_queryPort; - auto m_queryHost = host; - auto port_idx = m_queryHost.find_last_of(':'); + std::string queryPort; + auto queryHost = host; + auto port_idx = queryHost.find_last_of(':'); if(port_idx != std::string::npos) { - m_queryPort = m_queryHost.substr(port_idx + 1); - m_queryHost = m_queryHost.substr(0, port_idx); + queryPort = queryHost.substr(port_idx + 1); + queryHost = queryHost.substr(0, port_idx); } else - m_queryPort = "80"; + queryPort = "80"; - if(boost::starts_with(m_queryHost, "http://")) - m_queryHost.erase(m_queryHost.begin(), m_queryHost.begin() + 7); - else if(boost::starts_with(m_queryHost, "ws://")) - m_queryHost.erase(m_queryHost.begin(), m_queryHost.begin() + 5); + if(boost::starts_with(queryHost, "http://")) + queryHost.erase(queryHost.begin(), queryHost.begin() + 7); + else if(boost::starts_with(queryHost, "ws://")) + queryHost.erase(queryHost.begin(), queryHost.begin() + 5); boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(m_queryHost, m_queryPort); + boost::asio::ip::tcp::resolver::query query(queryHost, queryPort); boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query); return true; } @@ -65,6 +66,7 @@ bool resolve_ip(std::string host) } return false; } + namespace Protocols { OSCQueryDevice::OSCQueryDevice( @@ -201,11 +203,21 @@ void OSCQueryDevice::slot_createDevice() try { - std::unique_ptr ossia_settings - = std::make_unique(m_ctx, stgs.host.toStdString(), stgs.localPort); + std::unique_ptr ossia_settings; + if(stgs.dense) + { + ossia_settings + = std::make_unique( + m_ctx, stgs.host.toStdString(), stgs.localPort); + } + else + { + ossia_settings + = std::make_unique( + m_ctx, stgs.host.toStdString(), stgs.localPort); + } - auto& p = static_cast(*ossia_settings); - m_mirror = &p; + m_mirror = ossia_settings.get(); if(stgs.rate) { @@ -222,9 +234,9 @@ void OSCQueryDevice::slot_createDevice() deviceChanged(nullptr, m_dev.get()); - //p.set_command_callback([this] { sig_command(); }); - p.on_connection_closed.connect<&OSCQueryDevice::sig_disconnect>(*this); - p.on_connection_failure.connect<&OSCQueryDevice::sig_disconnect>(*this); + //m_mirror->set_command_callback([this] { sig_command(); }); + m_mirror->on_connection_closed.connect<&OSCQueryDevice::sig_disconnect>(*this); + m_mirror->on_connection_failure.connect<&OSCQueryDevice::sig_disconnect>(*this); setLogging_impl(Device::get_cur_logging(isLogging())); diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.hpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.hpp index c11c3f2fa9..2d5b883c93 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryDevice.hpp @@ -37,8 +37,7 @@ class OSCQueryDevice final : public Device::OwningDeviceInterface void slot_createDevice(); W_SLOT(slot_createDevice); - using mirror_proto = ossia::oscquery_asio::oscquery_mirror_asio_protocol; - mirror_proto* m_mirror{}; + ossia::net::protocol_base* m_mirror{}; bool m_connected{}; Device::DeviceSettings m_oldSettings; const ossia::net::network_context_ptr& m_ctx; diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolFactory.cpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolFactory.cpp index 3b09739365..5c5358ad09 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolFactory.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolFactory.cpp @@ -77,7 +77,7 @@ class OSCQueryEnumerator final : public DNSSDEnumerator .arg(websockets ? "ws" : "http") .arg(ws_ip.isEmpty() ? ip : ws_ip) .arg(ws_port.isEmpty() ? port : ws_port); - + sub.dense = doc.object()["EXTENSIONS"].toObject()["DENSE"].toBool(); set.deviceSpecificSettings = QVariant::fromValue(std::move(sub)); deviceAdded(set.name, set); ret->deleteLater(); diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.cpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.cpp index 22dc501b58..978594ab54 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.cpp @@ -44,12 +44,21 @@ OSCQueryProtocolSettingsWidget::OSCQueryProtocolSettingsWidget(QWidget* parent) "feedback from an external software. If 0, a random port will be chosen.")); checkForChanges(m_localPort); + m_dense = new QCheckBox("Dense message packing", this); + m_dense->setChecked(false); + m_dense->setEnabled(false); + m_localPort->setWhatsThis( + tr("Indicated whether the remote API supports dense packing of values ; useful " + "mainly for low-power embedded devices.")); + QFormLayout* layout = new QFormLayout; layout->addRow(tr("Name"), m_deviceNameEdit); layout->addRow(tr("Host"), m_localHostEdit); layout->addRow(tr("Local port"), m_localPort); layout->addRow(tr("Rate"), m_rate); + layout->addRow(new QLabel("Supported extensions: ")); + layout->addRow(m_dense); layout->addRow( "", @@ -60,15 +69,11 @@ OSCQueryProtocolSettingsWidget::OSCQueryProtocolSettingsWidget(QWidget* parent) setLayout(layout); - setDefaults(); -} - -void OSCQueryProtocolSettingsWidget::setDefaults() -{ m_deviceNameEdit->setText("newDevice"); m_localHostEdit->setText("ws://127.0.0.1:5678"); m_rate->setRate({}); m_localPort->setValue(0); + m_dense->setChecked(false); } Device::DeviceSettings OSCQueryProtocolSettingsWidget::getSettings() const @@ -81,6 +86,7 @@ Device::DeviceSettings OSCQueryProtocolSettingsWidget::getSettings() const OSCQuery.host = m_localHostEdit->text(); OSCQuery.rate = m_rate->rate(); OSCQuery.localPort = m_localPort->value(); + OSCQuery.dense = m_dense->isChecked(); s.deviceSpecificSettings = QVariant::fromValue(OSCQuery); return s; @@ -96,6 +102,7 @@ void OSCQueryProtocolSettingsWidget::setSettings(const Device::DeviceSettings& s m_localHostEdit->setText(OSCQuery.host); m_localPort->setValue(OSCQuery.localPort); m_rate->setRate(OSCQuery.rate); + m_dense->setChecked(OSCQuery.dense); } } } diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.hpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.hpp index 030ca2a8e4..9989da3c2a 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQueryProtocolSettingsWidget.hpp @@ -20,13 +20,11 @@ class OSCQueryProtocolSettingsWidget final : public Device::ProtocolSettingsWidg void setSettings(const Device::DeviceSettings& settings) override; -protected: - void setDefaults(); - protected: QLineEdit* m_deviceNameEdit{}; QLineEdit* m_localHostEdit{}; QSpinBox* m_localPort{}; + QCheckBox* m_dense{}; RateWidget* m_rate{}; }; diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettings.hpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettings.hpp index e5f32638cf..22edcdeba2 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettings.hpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettings.hpp @@ -12,6 +12,7 @@ struct OSCQuerySpecificSettings QString host; std::optional rate{}; int localPort{}; + bool dense{}; }; } Q_DECLARE_METATYPE(Protocols::OSCQuerySpecificSettings) diff --git a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettingsSerialization.cpp b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettingsSerialization.cpp index bd169e957f..0f15408904 100644 --- a/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettingsSerialization.cpp +++ b/src/plugins/score-plugin-protocols/Protocols/OSCQuery/OSCQuerySpecificSettingsSerialization.cpp @@ -8,14 +8,14 @@ template <> void DataStreamReader::read(const Protocols::OSCQuerySpecificSettings& n) { - m_stream << n.host << n.rate << n.localPort; + m_stream << n.host << n.rate << n.localPort << n.dense; insertDelimiter(); } template <> void DataStreamWriter::write(Protocols::OSCQuerySpecificSettings& n) { - m_stream >> n.host >> n.rate >> n.localPort; + m_stream >> n.host >> n.rate >> n.localPort >> n.dense; checkDelimiter(); } @@ -27,6 +27,8 @@ void JSONReader::read(const Protocols::OSCQuerySpecificSettings& n) obj["Rate"] = *n.rate; obj["LocalPort"] = n.localPort; + if(n.dense) + obj["Dense"] = true; } template <> @@ -37,4 +39,6 @@ void JSONWriter::write(Protocols::OSCQuerySpecificSettings& n) n.rate = it->toInt(); if(auto it = obj.tryGet("LocalPort")) n.localPort = it->toInt(); + if(auto it = obj.tryGet("Dense")) + n.localPort = it->toBool(); }