-
Notifications
You must be signed in to change notification settings - Fork 342
/
mythraopconnection.h
197 lines (167 loc) · 5.65 KB
/
mythraopconnection.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
#ifndef MYTHRAOPCONNECTION_H
#define MYTHRAOPCONNECTION_H
#include <QObject>
#include <QMap>
#include <QHash>
#include <QHostAddress>
#include <QStringList>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/aes.h>
#include "mythtvexp.h"
#include "mythnotification.h"
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}
class QTcpSocket;
class QUdpSocket;
class QTimer;
class AudioOutput;
class ServerPool;
class _NetStream;
typedef QHash<QString,QString> RawHash;
struct AudioData
{
uint8_t *data;
int32_t length;
int32_t frames;
};
struct AudioPacket
{
uint16_t seq;
QList<AudioData> *data;
};
class MTV_PUBLIC MythRAOPConnection : public QObject
{
Q_OBJECT
friend class MythRAOPDevice;
public:
MythRAOPConnection(QObject *parent, QTcpSocket *socket, QByteArray id,
int port);
~MythRAOPConnection();
bool Init(void);
QTcpSocket *GetSocket() { return m_socket; }
int GetDataPort() { return m_dataPort; }
bool HasAudio() { return m_audio; }
static QMap<QString,QString> decodeDMAP(const QByteArray &dmap);
static RSA *LoadKey(void);
static QString RSALastError(void) { return g_rsaLastError; }
private slots:
void readClient(void);
void udpDataReady(QByteArray buf, QHostAddress peer, quint16 port);
void timeout(void);
void audioRetry(void);
void newEventClient(QTcpSocket *client);
void deleteEventClient();
private:
void ProcessSync(const QByteArray &buf);
void SendResendRequest(uint64_t timestamp,
uint16_t expected, uint16_t got);
void ExpireResendRequests(uint64_t timestamp);
uint32_t decodeAudioPacket(uint8_t type, const QByteArray *buf,
QList<AudioData> *dest);
int ExpireAudio(uint64_t timestamp);
void ResetAudio(void);
void ProcessRequest(const QStringList &header,
const QByteArray &content);
void FinishResponse(_NetStream *stream, QTcpSocket *socket,
QString &option, QString &cseq);
void FinishAuthenticationResponse(_NetStream *stream, QTcpSocket *socket,
QString &cseq);
RawHash FindTags(const QStringList &lines);
bool CreateDecoder(void);
void DestroyDecoder(void);
bool OpenAudioDevice(void);
void CloseAudioDevice(void);
void StartAudioTimer(void);
void StopAudioTimer(void);
void CleanUp(void);
// time sync
void SendTimeRequest(void);
void ProcessTimeResponse(const QByteArray &buf);
uint64_t NTPToLocal(uint32_t sec, uint32_t ticks);
// incoming data packet
bool GetPacketType(const QByteArray &buf, uint8_t &type,
uint16_t &seq, uint64_t ×tamp);
// utility functions
int64_t AudioCardLatency(void);
QStringList splitLines(const QByteArray &lines);
QString stringFromSeconds(int seconds);
uint64_t framesToMs(uint64_t frames);
// notification functions
void SendNotification(bool update = false);
QTimer *m_watchdogTimer;
// comms socket
QTcpSocket *m_socket;
_NetStream *m_textStream;
QByteArray m_hardwareId;
QStringList m_incomingHeaders;
QByteArray m_incomingContent;
bool m_incomingPartial;
int32_t m_incomingSize;
QHostAddress m_peerAddress;
ServerPool *m_dataSocket;
int m_dataPort;
ServerPool *m_clientControlSocket;
int m_clientControlPort;
ServerPool *m_clientTimingSocket;
int m_clientTimingPort;
ServerPool *m_eventServer;
int m_eventPort;
QList<QTcpSocket *> m_eventClients;
// incoming audio
QMap<uint16_t,uint64_t> m_resends;
// crypto
QByteArray m_AESIV;
AES_KEY m_aesKey;
static RSA *g_rsa;
static QString g_rsaLastError;
// audio out
AudioOutput *m_audio;
AVCodec *m_codec;
AVCodecContext *m_codeccontext;
QList<int> m_audioFormat;
int m_channels;
int m_sampleSize;
int m_frameRate;
int m_framesPerPacket;
QTimer *m_dequeueAudioTimer;
QMap<uint64_t, AudioPacket> m_audioQueue;
uint32_t m_queueLength;
bool m_streamingStarted;
bool m_allowVolumeControl;
// packet index, increase after each resend packet request
uint16_t m_seqNum;
// audio/packet sync
uint16_t m_lastSequence;
uint64_t m_lastTimestamp;
uint64_t m_currentTimestamp;
uint16_t m_nextSequence;
uint64_t m_nextTimestamp;
int64_t m_bufferLength;
uint64_t m_timeLastSync;
int64_t m_cardLatency;
int64_t m_adjustedLatency;
bool m_audioStarted;
// clock sync
uint64_t m_masterTimeStamp;
uint64_t m_deviceTimeStamp;
uint64_t m_networkLatency;
int64_t m_clockSkew; // difference in ms between reference
// audio retry timer
QTimer *m_audioTimer;
//Current Stream Info
uint32_t m_progressStart;
uint32_t m_progressCurrent;
uint32_t m_progressEnd;
QByteArray m_artwork;
DMAP m_dmap;
//Authentication
QString m_nonce;
// Notification Center registration Id
int m_id;
private slots:
void ProcessAudio(void);
};
#endif // MYTHRAOPCONNECTION_H