Loading...
Searching...
No Matches
BitfocusContext.hpp
1#pragma once
2#include <boost/asio/io_context.hpp>
3#include <boost/asio/ip/udp.hpp>
4
5#include <QColor>
6#include <QCoreApplication>
7#include <QJsonArray>
8#include <QJsonDocument>
9#include <QJsonObject>
10#include <QMap>
11#include <QProcess>
12#include <QRegularExpression>
13#include <QSocketNotifier>
14#include <QUuid>
15
16#include <array>
17#include <functional>
18
19#include <verdigris>
20#if !defined(_WIN32)
21#include <sys/socket.h>
22#include <sys/un.h>
23
24#include <fcntl.h>
25#include <stdlib.h>
26#include <unistd.h>
27#endif
28namespace bitfocus
29{
30
31using module_configuration = std::map<QString, QVariant>;
33{
35 {
36 struct choice
37 {
38 QString id;
39 QString label;
40 };
41
42 QString id;
43 QString label;
44 // "static-text", "textinput", "number", "checkbox", "choices", "bonjour-device", "dropdown"
45 QString type;
46 QVariant value;
47 QString tooltip;
48 QString regex;
49 // ex. : "e=>!![\"TF\",\"DM3\",\"DM7\"].includes(e.model)&&(e.kaInterval=e.kaIntervalH,!0)",
50 QString isVisibleFn;
51 QVariant min;
52 QVariant max;
53 std::vector<choice> choices;
54 QVariant default_value{}; // true, a number, a string etc
55 double width{};
56 };
57
59 {
60 bool hasLearn{};
61 QString name;
62 std::vector<config_field> options;
63 };
65 {
66 QString name;
67 QVariant value;
68 };
70 {
71 bool hasLearn{};
72 bool isInverted{false};
73 bool disabled{false};
74 int upgradeIndex{0};
75 QString name;
76 std::vector<config_field> options;
77 QString type;
78 struct
79 {
80 QColor bgcolor;
81 QColor color;
82 } defaultStyle;
83 };
85 {
86 QString name;
87 QString category;
88 QString text;
89 QString type;
90 std::vector<QVariantMap> feedbacks;
91 std::vector<QVariantMap> steps;
92 };
93
95 {
96 QString id;
97 QString controlId;
98 QString definitionId;
99 QVariantMap options;
100 int imageWidth{72};
101 int imageHeight{72};
102 int upgradeIndex{-1};
103 bool disabled{false};
104 };
105
106 std::map<QString, action_definition> actions;
107 std::map<QString, variable_definition> variables;
108 std::map<QString, feedback_definition> feedbacks;
109 std::map<QString, preset_definition> presets;
110 std::vector<config_field> config_fields;
111 module_configuration config;
112};
113
114// note: callback id shared between both ends so every message has to be processed in order
115#if defined(_WIN32)
116struct win32_handles;
117struct module_handler_base : public QObject
118{
119 std::unique_ptr<win32_handles> handles{};
120 explicit module_handler_base(
121 QString node_path, QString module_path, QString entrypoint);
122 virtual ~module_handler_base();
123 void do_write(std::string_view res);
124 virtual void processMessage(std::string_view) = 0;
125};
126#else
127struct module_handler_base : public QObject
128{
129 char buf[16 * 4096]{};
130 std::vector<char> queue;
131 QProcess process{};
132 QSocketNotifier* socket{};
133 int pfd[2]{};
134
135 explicit module_handler_base(
136 QString node_path, QString module_path, QString entrypoint);
137 virtual ~module_handler_base();
138
139 void on_read(QSocketDescriptor, QSocketNotifier::Type);
140 void do_write(std::string_view res);
141
142 virtual void processMessage(std::string_view) = 0;
143};
144#endif
145
147{
148 W_OBJECT(module_handler)
149public:
150 explicit module_handler(
151 QString path, QString entrypoint, QString nodeVersion, QString apiversion,
152 module_configuration config);
153 virtual ~module_handler();
154
155 using module_handler_base::do_write;
156 void do_write(QString res);
157 QString jsonToString(QJsonObject obj);
158
159 void afterRegistration(std::function<void()>);
160
161 void processMessage(std::string_view v) override;
162
163 int writeRequest(QString name, QString p);
164 void writeReply(QJsonValue id, QString p);
165 void writeReply(QJsonValue id, QJsonObject p);
166 void writeReply(QJsonValue id, QString p, bool success);
167 void writeReply(QJsonValue id, QJsonObject p, bool success);
168
169 // Module -> app (requests handling)
170 void on_register(QJsonValue id);
171 void on_setActionDefinitions(QJsonArray obj);
172 void on_setVariableDefinitions(QJsonArray obj);
173 void on_setFeedbackDefinitions(QJsonArray obj);
174 void on_setPresetDefinitions(QJsonArray obj);
175 void on_setVariableValues(QJsonArray obj);
176 void on_set_status(QJsonObject obj);
177 void on_saveConfig(QJsonObject obj);
178 void on_parseVariablesInString(QJsonValue id, QJsonObject obj);
179 void on_updateFeedbackValues(QJsonObject obj);
180 void on_recordAction(QJsonObject obj);
181 void on_setCustomVariable(QJsonObject obj);
182 void on_sharedUdpSocketJoin(QJsonValue id, QJsonObject obj);
183 void on_sharedUdpSocketLeave(QJsonObject obj);
184 void on_sharedUdpSocketSend(QJsonObject obj);
185 void on_send_osc(QJsonObject obj);
186
187 module_data::config_field parseConfigField(QJsonObject f);
188
189 // Module -> app (replies handling)
190 void on_response_configFields(QJsonArray fields);
191
192 // App -> module
193
194 int init(QString label);
195 void send_success(QJsonValue id);
196 void updateConfigAndLabel(QString label, module_configuration conf);
197 int requestConfigFields();
198 void updateFeedbacks(const std::map<QString, module_data::feedback_instance>& feedbacks);
199 void feedbackLearnValues();
200 void feedbackDelete();
201 void variablesChanged();
202 void actionUpdate();
203 void actionDelete();
204 void actionLearnValues();
205 void actionRun(std::string_view act, QVariantMap options);
206 void destroy();
207 void executeHttpRequest(
208 const QString& method, const QString& path, const QString& body,
209 const QMap<QString, QString>& headers, const QMap<QString, QString>& query,
210 std::function<void(int status, QMap<QString, QString> respHeaders, QString respBody)>
211 callback);
212 void startStopRecordingActions();
213 void sharedUdpSocketMessage();
214 void sharedUdpSocketError();
215 const bitfocus::module_data& model();
216
217 void configurationParsed() W_SIGNAL(configurationParsed);
218 void variableChanged(QString var, QVariant val) W_SIGNAL(variableChanged, var, val);
219 void feedbackValueChanged(QString id, QString controlId, QVariant value)
220 W_SIGNAL(feedbackValueChanged, id, controlId, value);
221
222private:
223 struct shared_udp_handle
224 {
225 QString handleId;
226 QString family;
227 int portNumber{};
228 boost::asio::ip::udp::socket socket;
229 boost::asio::ip::udp::endpoint sender_endpoint;
230 std::array<char, 65536> recv_buffer{};
231
232 explicit shared_udp_handle(boost::asio::io_context& ctx)
233 : socket(ctx)
234 {
235 }
236 };
237
238 void start_udp_receive(shared_udp_handle* h);
239
240 bitfocus::module_data m_model;
241
242 boost::asio::io_context m_send_service;
243 boost::asio::ip::udp::socket m_socket{m_send_service};
244
245 std::map<QString, std::unique_ptr<shared_udp_handle>> m_shared_udp_handles;
246 std::map<int, std::function<void(int, QMap<QString, QString>, QString)>> m_httpCallbacks;
247
248 std::vector<std::function<void()>> m_afterRegistrationQueue;
249 int m_cbid{1};
250
251 int m_init_msg_id{-1};
252 int m_req_cfg_id{-1};
253
254 bool m_expects_label_updates{true};
255 bool m_hasHttpHandler{false};
256 bool m_registered{false};
257};
258
259} // namespace bitfocus
Definition ClipMode.hpp:10
Definition BitfocusContext.hpp:59
Definition BitfocusContext.hpp:37
Definition BitfocusContext.hpp:35
Definition BitfocusContext.hpp:70
Definition BitfocusContext.hpp:95
Definition BitfocusContext.hpp:85
Definition BitfocusContext.hpp:65
Definition BitfocusContext.hpp:33
Definition BitfocusContext.hpp:128
Definition BitfocusContext.hpp:147
Definition BitfocusContext.win32.cpp:17