diff options
Diffstat (limited to 'proto-osc')
| -rw-r--r-- | proto-osc/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | proto-osc/dialog.cpp | 38 | ||||
| -rw-r--r-- | proto-osc/dialog.hpp | 29 | ||||
| -rw-r--r-- | proto-osc/dialog.ui | 131 | ||||
| -rw-r--r-- | proto-osc/images/osc-icon.png | bin | 0 -> 868 bytes | |||
| -rw-r--r-- | proto-osc/lang/nl_NL.ts | 45 | ||||
| -rw-r--r-- | proto-osc/lang/ru_RU.ts | 45 | ||||
| -rw-r--r-- | proto-osc/lang/stub.ts | 45 | ||||
| -rw-r--r-- | proto-osc/lang/zh_CN.ts | 45 | ||||
| -rw-r--r-- | proto-osc/metadata.cpp | 8 | ||||
| -rw-r--r-- | proto-osc/metadata.hpp | 10 | ||||
| -rw-r--r-- | proto-osc/osc-res.qrc | 5 | ||||
| -rw-r--r-- | proto-osc/proto.cpp | 54 | ||||
| -rw-r--r-- | proto-osc/proto.hpp | 29 | ||||
| -rw-r--r-- | proto-osc/settings.hpp | 14 | 
15 files changed, 513 insertions, 0 deletions
| 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 <QHostAddress> +#include <QPalette> + +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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>OSC_Dialog</class> + <widget class="QWidget" name="OSC_Dialog"> +  <property name="windowModality"> +   <enum>Qt::NonModal</enum> +  </property> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>284</width> +    <height>102</height> +   </rect> +  </property> +  <property name="sizePolicy"> +   <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +    <horstretch>0</horstretch> +    <verstretch>0</verstretch> +   </sizepolicy> +  </property> +  <property name="minimumSize"> +   <size> +    <width>284</width> +    <height>102</height> +   </size> +  </property> +  <property name="windowTitle"> +   <string>OSC protocol settings</string> +  </property> +  <property name="windowIcon"> +   <iconset resource="osc-res.qrc"> +    <normaloff>:/images/osc-icon.png</normaloff>:/images/osc-icon.png</iconset> +  </property> +  <property name="layoutDirection"> +   <enum>Qt::LeftToRight</enum> +  </property> +  <property name="autoFillBackground"> +   <bool>false</bool> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout"> +   <item> +    <layout class="QFormLayout" name="formLayout_2"> +     <item row="0" column="0"> +      <widget class="QLabel" name="label"> +       <property name="text"> +        <string>Destination address</string> +       </property> +      </widget> +     </item> +     <item row="0" column="1"> +      <widget class="QLineEdit" name="address"> +       <property name="sizePolicy"> +        <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> +         <horstretch>0</horstretch> +         <verstretch>0</verstretch> +        </sizepolicy> +       </property> +       <property name="text"> +        <string/> +       </property> +       <property name="maxLength"> +        <number>256</number> +       </property> +      </widget> +     </item> +     <item row="1" column="0"> +      <widget class="QLabel" name="label_2"> +       <property name="text"> +        <string>Port</string> +       </property> +      </widget> +     </item> +     <item row="1" column="1"> +      <widget class="QSpinBox" name="port"> +       <property name="sizePolicy"> +        <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +         <horstretch>0</horstretch> +         <verstretch>0</verstretch> +        </sizepolicy> +       </property> +       <property name="maximum"> +        <number>65535</number> +       </property> +      </widget> +     </item> +    </layout> +   </item> +   <item> +    <widget class="QDialogButtonBox" name="buttonBox"> +     <property name="sizePolicy"> +      <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +       <horstretch>0</horstretch> +       <verstretch>0</verstretch> +      </sizepolicy> +     </property> +     <property name="standardButtons"> +      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> +     </property> +    </widget> +   </item> +  </layout> + </widget> + <resources> +  <include location="../gui/opentrack-res.qrc"/> +  <include location="osc-res.qrc"/> + </resources> + <connections/> + <designerdata> +  <property name="gridDeltaX"> +   <number>5</number> +  </property> +  <property name="gridDeltaY"> +   <number>5</number> +  </property> +  <property name="gridSnapX"> +   <bool>true</bool> +  </property> +  <property name="gridSnapY"> +   <bool>true</bool> +  </property> +  <property name="gridVisible"> +   <bool>false</bool> +  </property> + </designerdata> + <slots> +  <slot>startEngineClicked()</slot> +  <slot>stopEngineClicked()</slot> +  <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/proto-osc/images/osc-icon.png b/proto-osc/images/osc-icon.pngBinary files differ new file mode 100644 index 00000000..3ef546e9 --- /dev/null +++ b/proto-osc/images/osc-icon.png 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="nl_NL"> +<context> +    <name>OSC_Dialog</name> +    <message> +        <source>OSC protocol settings</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Port</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Destination address</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_metadata</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_proto</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Error binding socket to INADDR_ANY</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>%1: %2</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Invalid destination address '%1'</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru_RU"> +<context> +    <name>OSC_Dialog</name> +    <message> +        <source>OSC protocol settings</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Port</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Destination address</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_metadata</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_proto</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Error binding socket to INADDR_ANY</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>%1: %2</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Invalid destination address '%1'</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> +    <name>OSC_Dialog</name> +    <message> +        <source>OSC protocol settings</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Port</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Destination address</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_metadata</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_proto</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Error binding socket to INADDR_ANY</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>%1: %2</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Invalid destination address '%1'</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="zh_CN"> +<context> +    <name>OSC_Dialog</name> +    <message> +        <source>OSC protocol settings</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Port</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Destination address</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_metadata</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +</context> +<context> +    <name>osc_proto</name> +    <message> +        <source>Open Sound Control</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Error binding socket to INADDR_ANY</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>%1: %2</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Invalid destination address '%1'</source> +        <translation type="unfinished"></translation> +    </message> +</context> +</TS> 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 @@ +<RCC> +  <qresource prefix="/"> +    <file>images/osc-icon.png</file> +  </qresource> +</RCC> 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 <QQuaternion> +#include <QHostAddress> +#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 <sthalik@misaki.pl> + * + * 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 <QUdpSocket> +#include <QHostAddress> + +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 <QString> +#include "options/options.hpp" + +using namespace options; + +struct osc_settings : opts +{ +    value<QString> address; +    value<int> port; +    osc_settings() : opts("proto-osc"), address{b, "address", "127.0.0.1"}, +        port(b, "port", 53101) +    {} +}; | 
