From 051fb2f94f6364b80219a3c671bb953d2e54a140 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 21 Mar 2023 17:33:41 +0100 Subject: proto/osc: add open sound control output method --- proto-osc/CMakeLists.txt | 15 +++++ proto-osc/dialog.cpp | 38 ++++++++++++ proto-osc/dialog.hpp | 29 ++++++++++ proto-osc/dialog.ui | 131 ++++++++++++++++++++++++++++++++++++++++++ proto-osc/images/osc-icon.png | Bin 0 -> 868 bytes proto-osc/lang/nl_NL.ts | 45 +++++++++++++++ proto-osc/lang/ru_RU.ts | 45 +++++++++++++++ proto-osc/lang/stub.ts | 45 +++++++++++++++ proto-osc/lang/zh_CN.ts | 45 +++++++++++++++ proto-osc/metadata.cpp | 8 +++ proto-osc/metadata.hpp | 10 ++++ proto-osc/osc-res.qrc | 5 ++ proto-osc/proto.cpp | 54 +++++++++++++++++ proto-osc/proto.hpp | 29 ++++++++++ proto-osc/settings.hpp | 14 +++++ 15 files changed, 513 insertions(+) create mode 100644 proto-osc/CMakeLists.txt create mode 100644 proto-osc/dialog.cpp create mode 100644 proto-osc/dialog.hpp create mode 100644 proto-osc/dialog.ui create mode 100644 proto-osc/images/osc-icon.png create mode 100644 proto-osc/lang/nl_NL.ts create mode 100644 proto-osc/lang/ru_RU.ts create mode 100644 proto-osc/lang/stub.ts create mode 100644 proto-osc/lang/zh_CN.ts create mode 100644 proto-osc/metadata.cpp create mode 100644 proto-osc/metadata.hpp create mode 100644 proto-osc/osc-res.qrc create mode 100644 proto-osc/proto.cpp create mode 100644 proto-osc/proto.hpp create mode 100644 proto-osc/settings.hpp (limited to 'proto-osc') diff --git a/proto-osc/CMakeLists.txt b/proto-osc/CMakeLists.txt new file mode 100644 index 00000000..eeaf206c --- /dev/null +++ b/proto-osc/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SDK_OSCPACK "" CACHE PATH "oscpack build directory") +if(SDK_OSCPACK) + if(WIN32) + if(NOT EXISTS "${SDK_OSCPACK}/include/.") + message(FATAL_ERROR "SDK_OSCPACK should have 'include' subdirectory (or symlink) to src dir") + endif() + link_directories("${SDK_OSCPACK}") + include_directories("${SDK_OSCPACK}/include" "${SDK_OSCPACK}/include/oscpack") + else() + link_directories("${SDK_OSCPACK}/lib" "${SDK_OSCPACK}/lib32") + include_directories("${SDK_OSCPACK}/include/oscpack") + endif() + link_libraries(oscpack) + otr_module(proto-osc) +endif() diff --git a/proto-osc/dialog.cpp b/proto-osc/dialog.cpp new file mode 100644 index 00000000..54bf6885 --- /dev/null +++ b/proto-osc/dialog.cpp @@ -0,0 +1,38 @@ +#include "dialog.hpp" +#include +#include + +void osc_dialog::host_address_edited(const QString& str) +{ + bool bad = QHostAddress{str}.isNull(); + auto pal = pal_; + for (auto role : { QPalette::Highlight, QPalette::Window }) + if (bad) + pal.setColor(role, Qt::red); + ui.address->setPalette(pal); +} + +osc_dialog::osc_dialog() : + pal_{palette()} +{ + ui.setupUi( this ); + + tie_setting(s.address, ui.address); + tie_setting(s.port, ui.port); + connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &osc_dialog::doOK); + connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &osc_dialog::doCancel); + connect(ui.address, &QLineEdit::textChanged, this, &osc_dialog::host_address_edited); + host_address_edited(ui.address->text()); +} + +void osc_dialog::save() { s.b->save(); } +void osc_dialog::reload() { s.b->reload(); } + +void osc_dialog::doOK() { s.b->save(); close(); } +void osc_dialog::doCancel() { close(); } + +void osc_dialog::register_protocol(IProtocol*) {} +void osc_dialog::unregister_protocol() {} + +bool osc_dialog::embeddable() noexcept { return true; } +void osc_dialog::set_buttons_visible(bool x) noexcept { ui.buttonBox->setVisible(x); } diff --git a/proto-osc/dialog.hpp b/proto-osc/dialog.hpp new file mode 100644 index 00000000..29682843 --- /dev/null +++ b/proto-osc/dialog.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "settings.hpp" +#include "ui_dialog.h" +#include "api/plugin-api.hpp" + +class osc_dialog: public IProtocolDialog +{ + Q_OBJECT + +public: + osc_dialog(); + void register_protocol(IProtocol*) override; + void unregister_protocol() override; +private: + void set_buttons_visible(bool x) noexcept override; + bool embeddable() noexcept override; + void save() override; + void reload() override; + + Ui_OSC_Dialog ui; + osc_settings s; + const QPalette pal_; + +private slots: + void doOK(); + void doCancel(); + void host_address_edited(const QString& str); +}; diff --git a/proto-osc/dialog.ui b/proto-osc/dialog.ui new file mode 100644 index 00000000..5a078bbd --- /dev/null +++ b/proto-osc/dialog.ui @@ -0,0 +1,131 @@ + + + OSC_Dialog + + + Qt::NonModal + + + + 0 + 0 + 284 + 102 + + + + + 0 + 0 + + + + + 284 + 102 + + + + OSC protocol settings + + + + :/images/osc-icon.png:/images/osc-icon.png + + + Qt::LeftToRight + + + false + + + + + + + + Destination address + + + + + + + + 0 + 0 + + + + + + + 256 + + + + + + + Port + + + + + + + + 0 + 0 + + + + 65535 + + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + 5 + + + 5 + + + true + + + true + + + false + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/proto-osc/images/osc-icon.png b/proto-osc/images/osc-icon.png new file mode 100644 index 00000000..3ef546e9 Binary files /dev/null and b/proto-osc/images/osc-icon.png differ diff --git a/proto-osc/lang/nl_NL.ts b/proto-osc/lang/nl_NL.ts new file mode 100644 index 00000000..260b7adc --- /dev/null +++ b/proto-osc/lang/nl_NL.ts @@ -0,0 +1,45 @@ + + + + + OSC_Dialog + + OSC protocol settings + + + + Port + + + + Destination address + + + + + osc_metadata + + Open Sound Control + + + + + osc_proto + + Open Sound Control + + + + Error binding socket to INADDR_ANY + + + + %1: %2 + + + + Invalid destination address '%1' + + + + diff --git a/proto-osc/lang/ru_RU.ts b/proto-osc/lang/ru_RU.ts new file mode 100644 index 00000000..498d68d6 --- /dev/null +++ b/proto-osc/lang/ru_RU.ts @@ -0,0 +1,45 @@ + + + + + OSC_Dialog + + OSC protocol settings + + + + Port + + + + Destination address + + + + + osc_metadata + + Open Sound Control + + + + + osc_proto + + Open Sound Control + + + + Error binding socket to INADDR_ANY + + + + %1: %2 + + + + Invalid destination address '%1' + + + + diff --git a/proto-osc/lang/stub.ts b/proto-osc/lang/stub.ts new file mode 100644 index 00000000..20828cbd --- /dev/null +++ b/proto-osc/lang/stub.ts @@ -0,0 +1,45 @@ + + + + + OSC_Dialog + + OSC protocol settings + + + + Port + + + + Destination address + + + + + osc_metadata + + Open Sound Control + + + + + osc_proto + + Open Sound Control + + + + Error binding socket to INADDR_ANY + + + + %1: %2 + + + + Invalid destination address '%1' + + + + diff --git a/proto-osc/lang/zh_CN.ts b/proto-osc/lang/zh_CN.ts new file mode 100644 index 00000000..e0d49844 --- /dev/null +++ b/proto-osc/lang/zh_CN.ts @@ -0,0 +1,45 @@ + + + + + OSC_Dialog + + OSC protocol settings + + + + Port + + + + Destination address + + + + + osc_metadata + + Open Sound Control + + + + + osc_proto + + Open Sound Control + + + + Error binding socket to INADDR_ANY + + + + %1: %2 + + + + Invalid destination address '%1' + + + + diff --git a/proto-osc/metadata.cpp b/proto-osc/metadata.cpp new file mode 100644 index 00000000..9d69347d --- /dev/null +++ b/proto-osc/metadata.cpp @@ -0,0 +1,8 @@ +#include "metadata.hpp" +#include "proto.hpp" +#include "dialog.hpp" + +QString osc_metadata::name() { return tr("Open Sound Control"); } +QIcon osc_metadata::icon() { return QIcon(":/images/osc-icon.png"); } + +OPENTRACK_DECLARE_PROTOCOL(osc_proto, osc_dialog, osc_metadata) diff --git a/proto-osc/metadata.hpp b/proto-osc/metadata.hpp new file mode 100644 index 00000000..c0a947aa --- /dev/null +++ b/proto-osc/metadata.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "api/plugin-api.hpp" + +class osc_metadata : public Metadata +{ + Q_OBJECT + + QString name() override; + QIcon icon() override; +}; diff --git a/proto-osc/osc-res.qrc b/proto-osc/osc-res.qrc new file mode 100644 index 00000000..ade4c629 --- /dev/null +++ b/proto-osc/osc-res.qrc @@ -0,0 +1,5 @@ + + + images/osc-icon.png + + diff --git a/proto-osc/proto.cpp b/proto-osc/proto.cpp new file mode 100644 index 00000000..2f90957c --- /dev/null +++ b/proto-osc/proto.cpp @@ -0,0 +1,54 @@ +#include "proto.hpp" +#include "ui_dialog.h" +#include "api/plugin-api.hpp" +#include +#include +#include "osc/OscOutboundPacketStream.h" + +osc_proto::osc_proto() +{ + auto reload_fn = [this] { + dest = QHostAddress{s.address }; + port = (unsigned short)s.port; + }; + connect(&*s.b, &bundle_::changed, this, reload_fn); + connect(&*s.b, &bundle_::reloading, this, reload_fn); +} + +void osc_proto::pose(const double* data, const double*) +{ + if (dest.isNull()) + return; + + static constexpr unsigned buffer_size = 1024; + char buffer[buffer_size] = {}; + osc::OutboundPacketStream p{buffer, buffer_size}; + auto q = QQuaternion::fromEulerAngles((float)data[Pitch], (float)data[Yaw], (float)-data[Roll]).normalized(); + p << osc::BeginMessage("/bridge/quat") << q.scalar() << q.x() << q.y() << q.z() << osc::EndMessage; + sock.writeDatagram(p.Data(), (int)p.Size(), dest, port); +} + +module_status osc_proto::initialize() +{ + QString error; + + dest = QHostAddress{s.address }; + port = (unsigned short)s.port; + + if (dest.isNull()) + { + error = tr("Invalid destination address '%1'").arg(s.address); + goto fail; + } + + if (!sock.bind()) + { + error = tr("Error binding socket to INADDR_ANY"); + goto fail; + } + + return status_ok(); + +fail: + return { tr("%1: %2").arg(error, sock.errorString()) }; +} diff --git a/proto-osc/proto.hpp b/proto-osc/proto.hpp new file mode 100644 index 00000000..53a5dee4 --- /dev/null +++ b/proto-osc/proto.hpp @@ -0,0 +1,29 @@ +#pragma once + +/* Copyright (c) 2023 Stanislaw Halik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "settings.hpp" +#include "api/plugin-api.hpp" +#include +#include + +class osc_proto : public QObject, public IProtocol +{ + Q_OBJECT + + osc_settings s; + QUdpSocket sock; + QHostAddress dest; + unsigned short port = 0; + +public: + osc_proto(); + module_status initialize() override; + void pose(const double *headpose, const double*) override; + QString game_name() override { return tr("Open Sound Control"); } +}; diff --git a/proto-osc/settings.hpp b/proto-osc/settings.hpp new file mode 100644 index 00000000..edeb45c6 --- /dev/null +++ b/proto-osc/settings.hpp @@ -0,0 +1,14 @@ +#pragma once +#include +#include "options/options.hpp" + +using namespace options; + +struct osc_settings : opts +{ + value address; + value port; + osc_settings() : opts("proto-osc"), address{b, "address", "127.0.0.1"}, + port(b, "port", 53101) + {} +}; -- cgit v1.2.3