Skip to content
This repository was archived by the owner on Feb 16, 2025. It is now read-only.

Commit 9a5d225

Browse files
refactor(calls): make chatform sole owner of ToxCalls
* Keep ToxCall creation on call invite, since it tracks call state changes * Fix ending call in ChatForm after CoreAv ends call from remote * Pass ToxCall up on invite instead of answer, so that ownership is the same before or after answer * Do nothing if CoreAv tries to cancel call for non-existent call, to avoid loop of CoreAv ending call, causing ChatForm to reset, causing ToxCall to cancel call with CoreAv
1 parent 17d527c commit 9a5d225

File tree

5 files changed

+31
-19
lines changed

5 files changed

+31
-19
lines changed

src/core/coreav.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ CoreAV::CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> toxav, QMutex& toxCoreLock,
9292
connect(iterateTimer, &QTimer::timeout, this, &CoreAV::process);
9393
connect(coreavThread.get(), &QThread::finished, iterateTimer, &QTimer::stop);
9494
connect(coreavThread.get(), &QThread::started, this, &CoreAV::process);
95+
qRegisterMetaType<ToxFriendCallPtr>("ToxFriendCallPtr");
9596
}
9697

9798
void CoreAV::connectCallbacks(ToxAV& toxav)
@@ -201,7 +202,7 @@ bool CoreAV::isCallActive(const Group* g) const
201202
return it->second->isActive();
202203
}
203204

204-
CoreAV::ToxFriendCallPtr CoreAV::answerCall(uint32_t friendNum, bool video)
205+
bool CoreAV::answerCall(uint32_t friendNum, bool video)
205206
{
206207
QWriteLocker locker{&callsLock};
207208
QMutexLocker coreLocker{&coreLock};
@@ -215,12 +216,11 @@ CoreAV::ToxFriendCallPtr CoreAV::answerCall(uint32_t friendNum, bool video)
215216
if (toxav_answer(toxav.get(), friendNum, audioSettings.getAudioBitrate(),
216217
videoBitrate, &err)) {
217218
it->second->setActive(true);
218-
return it->second;
219+
return true;
219220
} else {
220221
qWarning() << "Failed to answer call with error" << err;
221222
toxav_call_control(toxav.get(), friendNum, TOXAV_CALL_CONTROL_CANCEL, nullptr);
222-
calls.erase(it);
223-
return {};
223+
return false;
224224
}
225225
}
226226

@@ -247,7 +247,7 @@ CoreAV::ToxFriendCallPtr CoreAV::startCall(uint32_t friendNum, bool video)
247247
// Call object must be owned by this thread or there will be locking problems with Audio
248248
call->moveToThread(this->thread());
249249
assert(call != nullptr);
250-
calls.emplace(friendNum, call);
250+
calls.emplace(friendNum, call.get());
251251
return call;
252252
}
253253

@@ -258,7 +258,6 @@ bool CoreAV::cancelCall(uint32_t friendNum)
258258

259259
auto it = calls.find(friendNum);
260260
if (it == calls.end()) {
261-
qWarning() << QString("Can't cancel call with %1, it doesn't exist!").arg(friendNum);
262261
return false;
263262
}
264263

@@ -533,7 +532,7 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
533532
// Must explicitely unlock, because a deadlock can happen via ChatForm/Audio
534533
locker.unlock();
535534

536-
emit self->avInvite(friendNum, video);
535+
emit self->avInvite(friendNum, video, call);
537536
}
538537

539538
void CoreAV::stateCallback(ToxAV* toxav, uint32_t friendNum, uint32_t state, void* vSelf)

src/core/coreav.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "src/core/toxcall.h"
2424

2525
#include <QObject>
26+
#include <QMetaType>
2627
#include <QMutex>
2728
#include <QReadWriteLock>
2829
#include <atomic>
@@ -43,14 +44,17 @@ class VideoFrame;
4344
class Core;
4445
struct vpx_image;
4546

47+
Q_DECLARE_METATYPE(std::shared_ptr<ToxFriendCall>)
48+
4649
class CoreAV : public QObject
4750
{
4851
Q_OBJECT
4952

5053
public:
5154
using CoreAVPtr = std::unique_ptr<CoreAV>;
55+
// must be shared for signal avInvites signal, even though ownership is not shared
5256
using ToxFriendCallPtr = std::shared_ptr<ToxFriendCall>;
53-
using ToxGroupCallPtr = std::shared_ptr<ToxGroupCall>;
57+
using ToxGroupCallPtr = std::unique_ptr<ToxGroupCall>;
5458

5559
static CoreAVPtr makeCoreAV(Tox* core, QMutex& toxCoreLock,
5660
IAudioSettings& audioSettings, IGroupSettings& groupSettings);
@@ -78,12 +82,12 @@ class CoreAV : public QObject
7882

7983
public slots:
8084
ToxFriendCallPtr startCall(uint32_t friendNum, bool video);
81-
ToxFriendCallPtr answerCall(uint32_t friendNum, bool video);
85+
bool answerCall(uint32_t friendNum, bool video);
8286
bool cancelCall(uint32_t friendNum);
8387
void start();
8488

8589
signals:
86-
void avInvite(uint32_t friendId, bool video);
90+
void avInvite(uint32_t friendId, bool video, ToxFriendCallPtr call);
8791
void avStart(uint32_t friendId, bool video);
8892
void avEnd(uint32_t friendId, bool error = false);
8993

@@ -129,13 +133,13 @@ private slots:
129133
* @brief Maps friend IDs to ToxFriendCall.
130134
* @note Need to use STL container here, because Qt containers need a copy constructor.
131135
*/
132-
std::map<uint32_t, ToxFriendCallPtr> calls;
136+
std::map<uint32_t, ToxFriendCall*> calls;
133137

134138
/**
135139
* @brief Maps group IDs to ToxGroupCalls.
136140
* @note Need to use STL container here, because Qt containers need a copy constructor.
137141
*/
138-
std::map<int, ToxGroupCallPtr> groupCalls;
142+
std::map<int, ToxGroupCall*> groupCalls;
139143

140144
// protect 'calls' and 'groupCalls'
141145
mutable QReadWriteLock callsLock{QReadWriteLock::Recursive};

src/widget/form/chatform.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,19 @@ void ChatForm::onAttachClicked()
276276
}
277277
}
278278

279-
void ChatForm::onAvInvite(uint32_t friendId, bool video)
279+
void ChatForm::onAvInvite(uint32_t friendId, bool video, std::shared_ptr<ToxFriendCall> call)
280280
{
281281
if (friendId != f->getId()) {
282282
return;
283283
}
284284

285+
if (this->call) {
286+
qWarning() << "ChatForm invited to call when already in one. "
287+
"This should have been caught by CoreAv!";
288+
}
289+
290+
this->call = call;
291+
285292
QString displayedName = f->getDisplayedName();
286293
insertChatMessage(ChatMessage::createChatInfoMessage(tr("%1 calling").arg(displayedName),
287294
ChatMessage::INFO,
@@ -324,6 +331,7 @@ void ChatForm::onAvEnd(uint32_t friendId, bool error)
324331
return;
325332
}
326333

334+
call.reset();
327335
headWidget->removeCallConfirm();
328336
// Fixes an OS X bug with ending a call while in full screen
329337
if (netcam && netcam->isFullScreen()) {
@@ -354,14 +362,15 @@ void ChatForm::onAnswerCallTriggered(bool video)
354362
emit acceptCall(friendId);
355363

356364
updateCallButtons();
357-
if (call) {
358-
qDebug() << "Stale call detected";
365+
if (!call) {
366+
qWarning() << "Trying to answer call without receiving an invite";
359367
}
360368

361369
CoreAV* av = core.getAv();
362-
call = av->answerCall(friendId, video);
363-
if (!call) {
370+
bool answered = av->answerCall(friendId, video);
371+
if (!answered) {
364372
qDebug() << "Failed to answer call";
373+
call.reset();
365374
updateCallButtons();
366375
stopCounter();
367376
hideNetcam();

src/widget/form/chatform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class ChatForm : public GenericChatForm
6868
void updateFriendActivity(Friend& frnd);
6969

7070
public slots:
71-
void onAvInvite(uint32_t friendId, bool video);
71+
void onAvInvite(uint32_t friendId, bool video, std::shared_ptr<ToxFriendCall> call);
7272
void onAvStart(uint32_t friendId, bool video);
7373
void onAvEnd(uint32_t friendId, bool error);
7474
void onAvatarChanged(const ToxPk& friendPk, const QPixmap& pic);

src/widget/form/groupchatform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ private slots:
7979
FlowLayout* namesListLayout;
8080
QLabel* nusersLabel;
8181
TabCompleter* tabber;
82-
std::shared_ptr<ToxGroupCall> call;
82+
std::unique_ptr<ToxGroupCall> call;
8383
};

0 commit comments

Comments
 (0)