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
|
/*
* Copyright (C) 2008-2010 The QXmpp developers
*
* Author:
* Jeremy Lainé
*
* Source:
* http://code.google.com/p/qxmpp
*
* This file is a part of QXmpp library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
#ifndef QXMPPCALLMANAGER_H
#define QXMPPCALLMANAGER_H
#include <QObject>
#include <QIODevice>
#include "QXmppClientExtension.h"
#include "QXmppJingleIq.h"
#include "QXmppLogger.h"
class QXmppCodec;
class QXmppIceConnection;
class QXmppJingleCandidate;
class QXmppJingleIq;
class QXmppJinglePayloadType;
/// \brief The QXmppCall class represents a Voice-Over-IP call to a remote party.
///
/// It acts as a QIODevice so that you can read / write audio samples, for
/// instance using a QAudioOutput and a QAudioInput.
///
/// \note THIS API IS NOT FINALIZED YET
class QXmppCall : public QIODevice
{
Q_OBJECT
public:
/// This enum is used to describe the direction of a call.
enum Direction
{
IncomingDirection, ///< The call is incoming.
OutgoingDirection, ///< The call is outgoing.
};
/// This enum is used to describe the state of a call.
enum State
{
OfferState = 0, ///< The remote part is being called.
ConnectingState = 1, ///< The call is being connected.
ActiveState = 2, ///< The call is active.
DisconnectingState = 3, ///< The call is being disconnected.
FinishedState = 4, ///< The call is finished.
};
QXmppCall::Direction direction() const;
QString jid() const;
QString sid() const;
QXmppCall::State state() const;
QXmppJinglePayloadType payloadType() const;
/// \cond
qint64 bytesAvailable() const;
bool isSequential() const;
/// \endcond
signals:
/// This signal is emitted when a call is connected.
///
/// Once this signal is emitted, you can connect a QAudioOutput and
/// QAudioInput to the call. You can determine the appropriate clockrate
/// and the number of channels by calling payloadType().
void connected();
/// This signal is emitted when a call is finished.
///
/// Note: Do not delete the call in the slot connected to this signal,
/// instead use deleteLater().
void finished();
/// \internal
void localCandidatesChanged();
/// This signal is emitted when the remote party is ringing.
void ringing();
/// This signal is emitted to send logging messages.
void logMessage(QXmppLogger::MessageType type, const QString &msg);
/// This signal is emitted when the call state changes.
void stateChanged(QXmppCall::State state);
public slots:
void accept();
void hangup();
private slots:
void datagramReceived(int component, const QByteArray &datagram);
void emitSignals();
void updateOpenMode();
void terminate();
void terminated();
protected:
/// \cond
qint64 readData(char * data, qint64 maxSize);
qint64 writeData(const char * data, qint64 maxSize);
/// \endcond
private:
QXmppCall(const QString &jid, QXmppCall::Direction direction, QObject *parent);
void setPayloadType(const QXmppJinglePayloadType &type);
void addRemoteCandidates(const QList<QXmppJingleCandidate> &candidates);
void setState(QXmppCall::State state);
Direction m_direction;
QString m_jid;
QString m_sid;
State m_state;
QString m_contentCreator;
QString m_contentName;
QXmppJinglePayloadType m_payloadType;
QList<QXmppJingleIq> m_requests;
QList<QXmppJinglePayloadType> m_commonPayloadTypes;
// ICE-UDP
QXmppIceConnection *m_connection;
// signals
bool m_signalsEmitted;
qint64 m_writtenSinceLastEmit;
// RTP
QXmppCodec *m_codec;
QByteArray m_incomingBuffer;
bool m_incomingBuffering;
int m_incomingMinimum;
quint16 m_incomingSequence;
quint32 m_incomingStamp;
quint16 m_outgoingChunk;
QByteArray m_outgoingBuffer;
bool m_outgoingMarker;
quint16 m_outgoingSequence;
quint32 m_outgoingStamp;
friend class QXmppCallManager;
};
/// \brief The QXmppCallManager class provides support for making and
/// receiving voice calls.
///
/// Session initiation is performed as described by XEP-0166: Jingle,
/// XEP-0167: Jingle RTP Sessions and XEP-0176: Jingle ICE-UDP Transport
/// Method.
///
/// The data stream is connected using Interactive Connectivity Establishment
/// (RFC 5245) and data is transferred using Real Time Protocol (RFC 3550)
/// packets.
///
/// \ingroup Managers
class QXmppCallManager : public QXmppClientExtension
{
Q_OBJECT
public:
QXmppCallManager(QXmppClient *client);
QXmppCall *call(const QString &jid);
/// \cond
QStringList discoveryFeatures() const;
bool handleStanza(QXmppStream *stream, const QDomElement &element);
/// \endcond
signals:
/// This signal is emitted when a new incoming call is received.
///
/// To accept the call, invoke the call's QXmppCall::accept() method.
/// To refuse the call, invoke the call's QXmppCall::abort() method.
void callReceived(QXmppCall *call);
private slots:
void callDestroyed(QObject *object);
void callStateChanged(QXmppCall::State state);
void iqReceived(const QXmppIq &iq);
void jingleIqReceived(const QXmppJingleIq &iq);
void localCandidatesChanged();
private:
bool checkPayloadTypes(QXmppCall *call, const QList<QXmppJinglePayloadType> &remotePayloadTypes);
QXmppCall *findCall(const QString &sid) const;
QXmppCall *findCall(const QString &sid, QXmppCall::Direction direction) const;
QList<QXmppJinglePayloadType> localPayloadTypes() const;
bool sendAck(const QXmppJingleIq &iq);
bool sendRequest(QXmppCall *call, const QXmppJingleIq &iq);
QList<QXmppCall*> m_calls;
};
#endif
|