-
Notifications
You must be signed in to change notification settings - Fork 0
/
SpectrumNextRemoteForm.h
225 lines (186 loc) · 5.59 KB
/
SpectrumNextRemoteForm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#ifndef QTSPECTRUMNEXTREMOTE_SPECTRUMNEXTREMOTEFORM_H
#define QTSPECTRUMNEXTREMOTE_SPECTRUMNEXTREMOTEFORM_H
#include <QWidget>
#include <QSettings>
#include <QTcpSocket>
#include <QQueue>
#include <QMutex>
#include <QTimer>
#include "NEX.h"
#include "RemoteCommand.h"
QT_BEGIN_NAMESPACE
namespace Ui
{
class SpectrumNextRemoteForm;
}
QT_END_NAMESPACE
class SpectrumNextRemoteForm : public QWidget
{
Q_OBJECT
enum class MessageType
{
Terminate = 0,
Connect,
Disconnect,
IsConnected,
Send,
Recv
};
class Message
{
public:
Message(MessageType mt, SpectrumNextRemoteForm* form):
_mt(mt),_form(form),_status_code{0} {}
virtual ~Message() {}
virtual void execute() {}
virtual void callback() {}
MessageType messageType() const { return _mt; }
int32_t statusCode() const { return _status_code; }
QString statusText() const { return _status_text; }
void setStatusCode(int32_t code) { _status_code = code; }
void setStatusText(QString text) { _status_text = text; }
protected:
SpectrumNextRemoteForm* _form;
QString _status_text;
int32_t _status_code;
const MessageType _mt;
};
class SendMessage:public Message
{
public:
SendMessage(SpectrumNextRemoteForm* form, const void* data, size_t size):
Message(MessageType::Send, form), _offset(0), _size(size)
{
_data = new uint8_t[size];
memcpy(_data, data, size);
}
~SendMessage() { delete[] _data; }
void execute() override
{
_form->logFormat("write %i bytes", _size - _offset);
_form->socket()->write((char*)&_data[_offset], _size - _offset);
}
void* data() const { return _data; }
off_t offset() const { return _offset; }
size_t size() const { return _size; }
bool progress(size_t n)
{
_offset += n;
return _offset == _size;
}
private:
uint8_t* _data;
off_t _offset;
size_t _size;
};
class RecvMessage:public Message
{
public:
RecvMessage(SpectrumNextRemoteForm* form, size_t size):
Message(MessageType::Recv, form), _data(new uint8_t[size]), _offset(0), _size(size) {}
~RecvMessage() { delete[] _data; }
void* data() const { return _data; }
off_t offset() const { return _offset; }
size_t size() const { return _size; }
size_t remain() const { return _size - _offset; }
bool progress(QTcpSocket* socket, size_t n)
{
_form->logFormat("read %i bytes", n);
assert(n <= remain());
socket->read((char*)&_data[_offset], n);
_offset += n;
return _offset == _size;
}
private:
uint8_t* _data;
off_t _offset;
size_t _size;
};
class DisconnectMessage:public Message
{
public:
DisconnectMessage(SpectrumNextRemoteForm* form):
Message(MessageType::Disconnect, form) {}
~DisconnectMessage() { }
void execute() override
{
QTcpSocket* socket = _form->socket();
if(socket != nullptr)
{
socket->close();
}
}
};
class GetBanksMessage: public SendMessage
{
static constexpr uint8_t _data[1] = {(uint8_t)RemoteCommand::GetBanks};
public:
GetBanksMessage(SpectrumNextRemoteForm* form):
SendMessage(form, (void*)_data, sizeof(_data)) {}
void callback() override
{
_form->onGetBanks(*this);
}
};
class GetBanksAnswerMessage: public RecvMessage
{
public:
GetBanksAnswerMessage(SpectrumNextRemoteForm* form):
RecvMessage(form, 8) {}
void callback() override
{
_form->onGetBanksAnswer(*this);
}
};
public:
explicit SpectrumNextRemoteForm(QWidget *parent = nullptr);
~SpectrumNextRemoteForm() override;
protected:
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent* event) override;
bool loadNEX(const QString& program);
void sendNEX();
void getBanks();
void remote(Message* message);
void remoteSendProgress(int n);
void remoteRecvProgress(int n);
void logLine(const QString& text);
void logFormat(const char *format, ...);
void connectToHost();
void disconnectFromHost();
void send(void *data, size_t size);
void emptyQueue();
public:
void onGetBanks(GetBanksMessage& message);
void onGetBanksAnswer(GetBanksAnswerMessage& message);
QTcpSocket* socket() { return _socket; }
private slots:
void connectPressed();
void sendPressed();
void browsePressed();
void addressLineChanged(const QString& text);
void fileLineChanged(const QString& text);
void flowSliderValueChanged(int);
void remoteConnected();
void remoteDisconnected();
void remoteBytesWritten(quint64 bytes);
void remoteReadyRead();
void remoteErrorOccurred(QAbstractSocket::SocketError);
void timerTimeout();
private:
Ui::SpectrumNextRemoteForm *ui;
QSettings _settings;
QString _workingDirectory;
QTimer _timer;
QTcpSocket* _socket;
QRecursiveMutex _message_queue_mtx;
QQueue<Message*> _message_queue;
QQueue<Message*> _recv_message_queue;
int64_t _flow_bytes_sent;
int64_t _flow_epoch;
NEX* _nex;
uint8_t* _banks;
int _flow_kbs;
bool _connected;
};
#endif //QTSPECTRUMNEXTREMOTE_SPECTRUMNEXTREMOTEFORM_H