RemoteApplication.hpp
1 #pragma once
2 #include <score/serialization/StringConstants.hpp>
3 
4 #include <QAbstractListModel>
5 #include <QQmlApplicationEngine>
6 #include <QtWebSockets/QtWebSockets>
7 
8 #include <wobjectdefs.h>
9 
10 #include <functional>
11 class QApplication;
12 
13 struct SyncInfo
14 {
15  QJsonValue path;
16  QString prettyName;
17  friend bool operator==(const SyncInfo& tn, const QJsonValue& rhs)
18  {
19  return tn.path == rhs;
20  }
21  friend bool operator!=(const SyncInfo& tn, const QJsonValue& rhs)
22  {
23  return tn.path != rhs;
24  }
25 };
26 
27 class TriggerList : public QAbstractListModel
28 {
29 public:
30  template <typename Fun>
31  void apply(Fun f)
32  {
33  beginResetModel();
34  f();
35  endResetModel();
36  }
37 
38  int rowCount(const QModelIndex&) const override { return timeSyncs.size(); }
39 
40  QVariant data(const QModelIndex& index, int) const override
41  {
42  if(index.row() >= timeSyncs.size())
43  return {};
44 
45  return timeSyncs[index.row()].prettyName;
46  }
47 
48  QHash<int, QByteArray> roleNames() const override
49  {
50  QHash<int, QByteArray> hash;
51  hash.insert(Qt::DisplayRole, "name");
52  return hash;
53  }
54  std::vector<SyncInfo> timeSyncs;
55 };
56 
57 struct WebSocketHandler : public QObject
58 {
59  W_OBJECT(WebSocketHandler)
60 
61 public:
62  TriggerList m_activeSyncs;
63 
64 private:
65  QWebSocket m_server;
66  ossia::hash_map<QString, std::function<void(const QJsonObject&)>> m_answers;
67 
68 public:
70  {
71  m_answers.insert(std::make_pair("TriggerAdded", [this](const QJsonObject& obj) {
72  qDebug() << obj;
73  auto json_it = obj.find("Path");
74  if(json_it == obj.end())
75  return;
76 
77  auto it = std::find(
78  m_activeSyncs.timeSyncs.begin(), m_activeSyncs.timeSyncs.end(), *json_it);
79  if(it == m_activeSyncs.timeSyncs.end())
80  {
81  m_activeSyncs.apply([=]() {
82  m_activeSyncs.timeSyncs.emplace_back(
83  SyncInfo{*json_it, obj[score::StringConstant().Name].toString()});
84  });
85  }
86  }));
87 
88  m_answers.insert(std::make_pair("TriggerRemoved", [this](const QJsonObject& obj) {
89  qDebug() << obj;
90  auto json_it = obj.find("Path");
91  if(json_it == obj.end())
92  return;
93 
94  auto it = std::find(
95  m_activeSyncs.timeSyncs.begin(), m_activeSyncs.timeSyncs.end(), *json_it);
96  if(it != m_activeSyncs.timeSyncs.end())
97  {
98  m_activeSyncs.apply([=]() { m_activeSyncs.timeSyncs.erase(it); });
99  }
100  }));
101 
102  connect(
103  &m_server, &QWebSocket::textMessageReceived, this,
104  &WebSocketHandler::processTextMessage);
105  connect(
106  &m_server, &QWebSocket::binaryMessageReceived, this,
107  &WebSocketHandler::processBinaryMessage);
108  connect(&m_server, &QWebSocket::connected, this, [] { qDebug("yolooo"); });
109  connect(
110  &m_server,
111  static_cast<void (QWebSocket::*)(QAbstractSocket::SocketError)>(
112  &QWebSocket::error),
113  this, [=](QAbstractSocket::SocketError) { qDebug() << m_server.errorString(); });
114 
115  m_server.open(QUrl("ws://147.210.128.72:10212"));
116  }
117 
118  ~WebSocketHandler() { m_server.close(); }
119 
120  void processTextMessage(const QString& message)
121  {
122  processBinaryMessage(message.toLatin1());
123  }
124 
125  void processBinaryMessage(QByteArray message)
126  {
127  QJsonParseError error;
128  auto doc = QJsonDocument::fromJson(std::move(message), &error);
129  if(error.error)
130  return;
131 
132  auto obj = doc.object();
133  auto it = obj.find("Message");
134  if(it == obj.end())
135  return;
136 
137  auto mess = it->toString();
138  auto answer_it = m_answers.find(mess);
139  if(answer_it == m_answers.end())
140  return;
141 
142  answer_it->second(obj);
143  }
144 
145  void on_rowPressed(int i)
146  {
147  if(i >= m_activeSyncs.timeSyncs.size())
148  return;
149 
150  auto tn = m_activeSyncs.timeSyncs[i];
151 
152  QJsonObject mess;
153  mess[score::StringConstant().Message] = "Trigger";
154  mess[score::StringConstant().Path] = tn.path;
155  QJsonDocument doc{mess};
156  auto json = doc.toJson();
157 
158  m_server.sendTextMessage(json);
159  }
160  W_SLOT(on_rowPressed)
161 
162  void on_play()
163  {
164  QJsonObject mess;
165  mess[score::StringConstant().Message] = "Play";
166  m_server.sendTextMessage(QJsonDocument{mess}.toJson());
167  }
168  W_SLOT(on_play)
169 
170  void on_pause()
171  {
172  QJsonObject mess;
173  mess[score::StringConstant().Message] = "Pause";
174  m_server.sendTextMessage(QJsonDocument{mess}.toJson());
175  }
176  W_SLOT(on_pause)
177 
178  void on_stop()
179  {
180  QJsonObject mess;
181  mess[score::StringConstant().Message] = "Stop";
182  m_server.sendTextMessage(QJsonDocument{mess}.toJson());
183  }
184  W_SLOT(on_stop)
185 
186  void on_addressChanged(QString addr)
187  {
188  m_server.close();
189 
190  m_activeSyncs.apply([this]() { m_activeSyncs.timeSyncs.clear(); });
191 
192  m_server.open(QUrl{addr});
193  }
194  W_SLOT(on_addressChanged)
195 };
196 
197 class RemoteApplication final : QObject
198 {
199 public:
200  RemoteApplication(int& argc, char** argv);
202 
203  int exec();
204 
205  // Base stuff.
206  QApplication* m_app;
207 
208  QQmlApplicationEngine engine;
209  WebSocketHandler m_triggers;
210 };
Definition: RemoteApplication.hpp:198
Definition: RemoteApplication.hpp:28
Definition: RemoteApplication.hpp:14
Definition: RemoteApplication.hpp:58