1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

refactor: make ToxCall non-moveable

We don't need move functionality and the code for it is complex and
error prone.
This commit is contained in:
sudden6 2019-01-27 21:47:28 +01:00
parent a66490f127
commit b7b9b58d42
No known key found for this signature in database
GPG Key ID: 279509B499E032B9
4 changed files with 50 additions and 127 deletions

View File

@ -73,13 +73,13 @@
* @brief Maps friend IDs to ToxFriendCall. * @brief Maps friend IDs to ToxFriendCall.
* @note Need to use STL container here, because Qt containers need a copy constructor. * @note Need to use STL container here, because Qt containers need a copy constructor.
*/ */
std::map<uint32_t, ToxFriendCall> CoreAV::calls; std::map<uint32_t, CoreAV::ToxFriendCallPtr> CoreAV::calls;
/** /**
* @brief Maps group IDs to ToxGroupCalls. * @brief Maps group IDs to ToxGroupCalls.
* @note Need to use STL container here, because Qt containers need a copy constructor. * @note Need to use STL container here, because Qt containers need a copy constructor.
*/ */
std::map<int, ToxGroupCall> CoreAV::groupCalls; std::map<int, CoreAV::ToxGroupCallPtr> CoreAV::groupCalls;
CoreAV::CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> toxav) CoreAV::CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> toxav)
: toxav{std::move(toxav)} : toxav{std::move(toxav)}
@ -208,7 +208,7 @@ bool CoreAV::isCallActive(const Friend* f) const
if (it == calls.end()) { if (it == calls.end()) {
return false; return false;
} }
return isCallStarted(f) && it->second.isActive(); return isCallStarted(f) && it->second->isActive();
} }
/** /**
@ -222,13 +222,13 @@ bool CoreAV::isCallActive(const Group* g) const
if (it == groupCalls.end()) { if (it == groupCalls.end()) {
return false; return false;
} }
return isCallStarted(g) && it->second.isActive(); return isCallStarted(g) && it->second->isActive();
} }
bool CoreAV::isCallVideoEnabled(const Friend* f) const bool CoreAV::isCallVideoEnabled(const Friend* f) const
{ {
auto it = calls.find(f->getId()); auto it = calls.find(f->getId());
return isCallStarted(f) && it->second.getVideoEnabled(); return isCallStarted(f) && it->second->getVideoEnabled();
} }
bool CoreAV::answerCall(uint32_t friendNum, bool video) bool CoreAV::answerCall(uint32_t friendNum, bool video)
@ -255,7 +255,7 @@ bool CoreAV::answerCall(uint32_t friendNum, bool video)
const uint32_t videoBitrate = video ? VIDEO_DEFAULT_BITRATE : 0; const uint32_t videoBitrate = video ? VIDEO_DEFAULT_BITRATE : 0;
if (toxav_answer(toxav.get(), friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, &err)) { if (toxav_answer(toxav.get(), friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, &err)) {
it->second.setActive(true); it->second->setActive(true);
return true; return true;
} else { } else {
qWarning() << "Failed to answer call with error" << err; qWarning() << "Failed to answer call with error" << err;
@ -293,8 +293,10 @@ bool CoreAV::startCall(uint32_t friendNum, bool video)
if (!toxav_call(toxav.get(), friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, nullptr)) if (!toxav_call(toxav.get(), friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, nullptr))
return false; return false;
auto ret = calls.insert(std::make_pair(friendNum, ToxFriendCall(friendNum, video, *this))); ToxFriendCallPtr call = ToxFriendCallPtr(new ToxFriendCall(friendNum, video, *this));
ret.first->second.startTimeout(friendNum); assert(call != nullptr);
auto ret = calls.emplace(friendNum, std::move(call));
ret.first->second->startTimeout(friendNum);
return true; return true;
} }
@ -359,7 +361,7 @@ bool CoreAV::sendCallAudio(uint32_t callId, const int16_t* pcm, size_t samples,
return false; return false;
} }
ToxFriendCall const& call = it->second; ToxFriendCall const& call = *it->second;
if (call.getMuteMic() || !call.isActive() if (call.getMuteMic() || !call.isActive()
|| !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A)) { || !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A)) {
@ -395,7 +397,7 @@ void CoreAV::sendCallVideo(uint32_t callId, std::shared_ptr<VideoFrame> vframe)
return; return;
} }
ToxFriendCall& call = it->second; ToxFriendCall& call = *it->second;
if (!call.getVideoEnabled() || !call.isActive() if (!call.getVideoEnabled() || !call.isActive()
|| !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V)) { || !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V)) {
@ -442,7 +444,7 @@ void CoreAV::toggleMuteCallInput(const Friend* f)
{ {
auto it = calls.find(f->getId()); auto it = calls.find(f->getId());
if (f && (it != calls.end())) { if (f && (it != calls.end())) {
ToxCall& call = it->second; ToxCall& call = *it->second;
call.setMuteMic(!call.getMuteMic()); call.setMuteMic(!call.getMuteMic());
} }
} }
@ -455,7 +457,7 @@ void CoreAV::toggleMuteCallOutput(const Friend* f)
{ {
auto it = calls.find(f->getId()); auto it = calls.find(f->getId());
if (f && (it != calls.end())) { if (f && (it != calls.end())) {
ToxCall& call = it->second; ToxCall& call = *it->second;
call.setMuteVol(!call.getMuteVol()); call.setMuteVol(!call.getMuteVol());
} }
} }
@ -494,7 +496,7 @@ void CoreAV::groupCallCallback(void* tox, uint32_t group, uint32_t peer, const i
return; return;
} }
ToxGroupCall& call = it->second; ToxGroupCall& call = *it->second;
if (call.getMuteVol() || !call.isActive()) { if (call.getMuteVol() || !call.isActive()) {
return; return;
@ -519,7 +521,7 @@ void CoreAV::invalidateGroupCallPeerSource(int group, ToxPk peerPk)
if (it == groupCalls.end()) { if (it == groupCalls.end()) {
return; return;
} }
it->second.removePeer(peerPk); it->second->removePeer(peerPk);
} }
/** /**
@ -536,7 +538,7 @@ VideoSource* CoreAV::getVideoSourceFromCall(int friendNum) const
return nullptr; return nullptr;
} }
return it->second.getVideoSource(); return it->second->getVideoSource();
} }
/** /**
@ -548,12 +550,14 @@ void CoreAV::joinGroupCall(int groupId)
{ {
qDebug() << QString("Joining group call %1").arg(groupId); qDebug() << QString("Joining group call %1").arg(groupId);
auto ret = groupCalls.insert(std::pair<int, ToxGroupCall>(groupId, ToxGroupCall{groupId, *this})); ToxGroupCallPtr groupcall = ToxGroupCallPtr(new ToxGroupCall{groupId, *this});
assert(groupcall != nullptr);
auto ret = groupCalls.emplace(groupId, std::move(groupcall));
if (ret.second == false) { if (ret.second == false) {
qWarning() << "This group call already exists, not joining!"; qWarning() << "This group call already exists, not joining!";
return; return;
} }
ret.first->second.setActive(true); ret.first->second->setActive(true);
} }
/** /**
@ -571,12 +575,12 @@ void CoreAV::leaveGroupCall(int groupId)
bool CoreAV::sendGroupCallAudio(int groupId, const int16_t* pcm, size_t samples, uint8_t chans, bool CoreAV::sendGroupCallAudio(int groupId, const int16_t* pcm, size_t samples, uint8_t chans,
uint32_t rate) const uint32_t rate) const
{ {
std::map<int, ToxGroupCall>::const_iterator it = groupCalls.find(groupId); std::map<int, ToxGroupCallPtr>::const_iterator it = groupCalls.find(groupId);
if (it == groupCalls.end()) { if (it == groupCalls.end()) {
return false; return false;
} }
if (!it->second.isActive() || it->second.getMuteMic()) { if (!it->second->isActive() || it->second->getMuteMic()) {
return true; return true;
} }
@ -595,7 +599,7 @@ void CoreAV::muteCallInput(const Group* g, bool mute)
{ {
auto it = groupCalls.find(g->getId()); auto it = groupCalls.find(g->getId());
if (g && (it != groupCalls.end())) { if (g && (it != groupCalls.end())) {
it->second.setMuteMic(mute); it->second->setMuteMic(mute);
} }
} }
@ -608,7 +612,7 @@ void CoreAV::muteCallOutput(const Group* g, bool mute)
{ {
auto it = groupCalls.find(g->getId()); auto it = groupCalls.find(g->getId());
if (g && (it != groupCalls.end())) { if (g && (it != groupCalls.end())) {
it->second.setMuteVol(mute); it->second->setMuteVol(mute);
} }
} }
@ -625,7 +629,7 @@ bool CoreAV::isGroupCallInputMuted(const Group* g) const
const uint32_t groupId = g->getId(); const uint32_t groupId = g->getId();
auto it = groupCalls.find(groupId); auto it = groupCalls.find(groupId);
return (it != groupCalls.end()) && it->second.getMuteMic(); return (it != groupCalls.end()) && it->second->getMuteMic();
} }
/** /**
@ -641,7 +645,7 @@ bool CoreAV::isGroupCallOutputMuted(const Group* g) const
const uint32_t groupId = g->getId(); const uint32_t groupId = g->getId();
auto it = groupCalls.find(groupId); auto it = groupCalls.find(groupId);
return (it != groupCalls.end()) && it->second.getMuteVol(); return (it != groupCalls.end()) && it->second->getMuteVol();
} }
/** /**
@ -656,7 +660,7 @@ bool CoreAV::isCallInputMuted(const Friend* f) const
} }
const uint32_t friendId = f->getId(); const uint32_t friendId = f->getId();
auto it = calls.find(friendId); auto it = calls.find(friendId);
return (it != calls.end()) && it->second.getMuteMic(); return (it != calls.end()) && it->second->getMuteMic();
} }
/** /**
@ -671,7 +675,7 @@ bool CoreAV::isCallOutputMuted(const Friend* f) const
} }
const uint32_t friendId = f->getId(); const uint32_t friendId = f->getId();
auto it = calls.find(friendId); auto it = calls.find(friendId);
return (it != calls.end()) && it->second.getMuteVol(); return (it != calls.end()) && it->second->getMuteVol();
} }
/** /**
@ -680,12 +684,12 @@ bool CoreAV::isCallOutputMuted(const Friend* f) const
void CoreAV::invalidateCallSources() void CoreAV::invalidateCallSources()
{ {
for (auto& kv : groupCalls) { for (auto& kv : groupCalls) {
kv.second.clearPeers(); kv.second->clearPeers();
} }
for (auto& kv : calls) { for (auto& kv : calls) {
// TODO: this is wrong, "0" is a valid source id // TODO: this is wrong, "0" is a valid source id
kv.second.setAlSource(0); kv.second->setAlSource(0);
} }
} }
@ -698,7 +702,7 @@ void CoreAV::sendNoVideo()
// We don't change the audio bitrate, but we signal that we're not sending video anymore // We don't change the audio bitrate, but we signal that we're not sending video anymore
qDebug() << "CoreAV: Signaling end of video sending"; qDebug() << "CoreAV: Signaling end of video sending";
for (auto& kv : calls) { for (auto& kv : calls) {
ToxFriendCall& call = kv.second; ToxFriendCall& call = *kv.second;
toxav_video_set_bit_rate(toxav.get(), kv.first, 0, nullptr); toxav_video_set_bit_rate(toxav.get(), kv.first, 0, nullptr);
call.setNullVideoBitrate(true); call.setNullVideoBitrate(true);
} }
@ -725,8 +729,10 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
return; return;
} }
auto it = self->calls.insert( ToxFriendCallPtr call = ToxFriendCallPtr(new ToxFriendCall{friendNum, video, *self});
std::pair<uint32_t, ToxFriendCall>(friendNum, ToxFriendCall{friendNum, video, *self})); assert(call != nullptr);
auto it = self->calls.emplace(friendNum, std::move(call));
if (it.second == false) { if (it.second == false) {
/// Hanging up from a callback is supposed to be UB, /// Hanging up from a callback is supposed to be UB,
/// but since currently the toxav callbacks are fired from the toxcore thread, /// but since currently the toxav callbacks are fired from the toxcore thread,
@ -744,7 +750,7 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
state |= TOXAV_FRIEND_CALL_STATE_SENDING_A | TOXAV_FRIEND_CALL_STATE_ACCEPTING_A; state |= TOXAV_FRIEND_CALL_STATE_SENDING_A | TOXAV_FRIEND_CALL_STATE_ACCEPTING_A;
if (video) if (video)
state |= TOXAV_FRIEND_CALL_STATE_SENDING_V | TOXAV_FRIEND_CALL_STATE_ACCEPTING_V; state |= TOXAV_FRIEND_CALL_STATE_SENDING_V | TOXAV_FRIEND_CALL_STATE_ACCEPTING_V;
it.first->second.setState(static_cast<TOXAV_FRIEND_CALL_STATE>(state)); it.first->second->setState(static_cast<TOXAV_FRIEND_CALL_STATE>(state));
// note: changed to self-> // note: changed to self->
emit reinterpret_cast<CoreAV*>(self)->avInvite(friendNum, video); emit reinterpret_cast<CoreAV*>(self)->avInvite(friendNum, video);
@ -779,7 +785,7 @@ void CoreAV::stateCallback(ToxAV* toxav, uint32_t friendNum, uint32_t state, voi
return; return;
} }
ToxFriendCall& call = it->second; ToxFriendCall& call = *it->second;
if (state & TOXAV_FRIEND_CALL_STATE_ERROR) { if (state & TOXAV_FRIEND_CALL_STATE_ERROR) {
qWarning() << "Call with friend" << friendNum << "died of unnatural causes!"; qWarning() << "Call with friend" << friendNum << "died of unnatural causes!";
@ -874,7 +880,7 @@ void CoreAV::audioFrameCallback(ToxAV*, uint32_t friendNum, const int16_t* pcm,
return; return;
} }
ToxFriendCall& call = it->second; ToxFriendCall& call = *it->second;
if (call.getMuteVol()) { if (call.getMuteVol()) {
return; return;
@ -899,7 +905,7 @@ void CoreAV::videoFrameCallback(ToxAV*, uint32_t friendNum, uint16_t w, uint16_t
return; return;
} }
CoreVideoSource* videoSource = it->second.getVideoSource(); CoreVideoSource* videoSource = it->second->getVideoSource();
if (!videoSource) { if (!videoSource) {
return; return;
} }

View File

@ -129,8 +129,10 @@ private:
std::unique_ptr<ToxAV, ToxAVDeleter> toxav; std::unique_ptr<ToxAV, ToxAVDeleter> toxav;
std::unique_ptr<QThread> coreavThread; std::unique_ptr<QThread> coreavThread;
QTimer* iterateTimer = nullptr; QTimer* iterateTimer = nullptr;
static std::map<uint32_t, ToxFriendCall> calls; using ToxFriendCallPtr = std::unique_ptr<ToxFriendCall>;
static std::map<int, ToxGroupCall> groupCalls; static std::map<uint32_t, ToxFriendCallPtr> calls;
using ToxGroupCallPtr = std::unique_ptr<ToxGroupCall>;
static std::map<int, ToxGroupCallPtr> groupCalls;
std::atomic_flag threadSwitchLock; std::atomic_flag threadSwitchLock;
friend class Audio; friend class Audio;

View File

@ -34,29 +34,6 @@ ToxCall::ToxCall(bool VideoEnabled, CoreAV& av)
{ {
} }
/**
* @brief ToxCall move constructor
* @param other object moved from
*/
ToxCall::ToxCall(ToxCall&& other) noexcept : active{other.active},
av{other.av},
audioInConn{other.audioInConn},
muteMic{other.muteMic},
muteVol{other.muteVol},
videoSource{other.videoSource},
videoInConn{other.videoInConn},
videoEnabled{other.videoEnabled},
nullVideoBitrate{other.nullVideoBitrate}
{
Audio& audio = Audio::getInstance();
audio.subscribeInput();
other.audioInConn = QMetaObject::Connection();
other.videoInConn = QMetaObject::Connection();
other.videoEnabled = false; // we don't need to subscribe video because other won't unsubscribe
other.videoSource = nullptr;
other.av = nullptr;
}
ToxCall::~ToxCall() ToxCall::~ToxCall()
{ {
Audio& audio = Audio::getInstance(); Audio& audio = Audio::getInstance();
@ -69,36 +46,6 @@ ToxCall::~ToxCall()
} }
} }
/**
* @brief ToxCall move assignement
* @param other object moved from
* @return object moved to
*/
ToxCall& ToxCall::operator=(ToxCall&& other) noexcept
{
QObject::disconnect(audioInConn);
audioInConn = other.audioInConn;
other.audioInConn = QMetaObject::Connection();
active = other.active;
muteMic = other.muteMic;
muteVol = other.muteVol;
Audio::getInstance().subscribeInput();
videoInConn = other.videoInConn;
other.videoInConn = QMetaObject::Connection();
videoEnabled = other.videoEnabled;
other.videoEnabled = false;
nullVideoBitrate = other.nullVideoBitrate;
videoSource = other.videoSource;
other.videoSource = nullptr;
av = other.av;
other.av = nullptr;
return *this;
}
bool ToxCall::isActive() const bool ToxCall::isActive() const
{ {
return active; return active;
@ -201,22 +148,6 @@ ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av)
} }
} }
ToxFriendCall::ToxFriendCall(ToxFriendCall &&other) noexcept
: ToxCall(std::move(other))
, alSource{other.alSource}
{
other.alSource = 0;
}
ToxFriendCall& ToxFriendCall::operator=(ToxFriendCall &&other) noexcept
{
ToxCall::operator=(std::move(other));
alSource = other.alSource;
other.alSource = 0;
return *this;
}
ToxFriendCall::~ToxFriendCall() ToxFriendCall::~ToxFriendCall()
{ {
auto& audio = Audio::getInstance(); auto& audio = Audio::getInstance();
@ -273,13 +204,6 @@ ToxGroupCall::ToxGroupCall(int GroupNum, CoreAV& av)
} }
} }
ToxGroupCall::ToxGroupCall(ToxGroupCall&& other) noexcept
: ToxCall(std::move(other)), peers{other.peers}
{
// all peers were moved, this ensures audio output is unsubscribed only once
other.peers.clear();
}
ToxGroupCall::~ToxGroupCall() ToxGroupCall::~ToxGroupCall()
{ {
Audio& audio = Audio::getInstance(); Audio& audio = Audio::getInstance();
@ -289,15 +213,6 @@ ToxGroupCall::~ToxGroupCall()
} }
} }
ToxGroupCall& ToxGroupCall::operator=(ToxGroupCall&& other) noexcept
{
ToxCall::operator=(std::move(other));
peers = other.peers;
other.peers.clear();
return *this;
}
void ToxGroupCall::removePeer(ToxPk peerId) void ToxGroupCall::removePeer(ToxPk peerId)
{ {
auto& audio = Audio::getInstance(); auto& audio = Audio::getInstance();

View File

@ -25,10 +25,10 @@ protected:
public: public:
ToxCall(const ToxCall& other) = delete; ToxCall(const ToxCall& other) = delete;
ToxCall(ToxCall&& other) noexcept; ToxCall(ToxCall&& other) = delete;
ToxCall& operator=(const ToxCall& other) = delete; ToxCall& operator=(const ToxCall& other) = delete;
ToxCall& operator=(ToxCall&& other) noexcept; ToxCall& operator=(ToxCall&& other) = delete;
bool isActive() const; bool isActive() const;
void setActive(bool value); void setActive(bool value);
@ -66,8 +66,8 @@ class ToxFriendCall : public ToxCall
public: public:
ToxFriendCall() = delete; ToxFriendCall() = delete;
ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av); ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av);
ToxFriendCall(ToxFriendCall&& other) noexcept; ToxFriendCall(ToxFriendCall&& other) = delete;
ToxFriendCall& operator=(ToxFriendCall&& other) noexcept; ToxFriendCall& operator=(ToxFriendCall&& other) = delete;
~ToxFriendCall(); ~ToxFriendCall();
void startTimeout(uint32_t callId); void startTimeout(uint32_t callId);
@ -93,10 +93,10 @@ class ToxGroupCall : public ToxCall
public: public:
ToxGroupCall() = delete; ToxGroupCall() = delete;
ToxGroupCall(int GroupNum, CoreAV& av); ToxGroupCall(int GroupNum, CoreAV& av);
ToxGroupCall(ToxGroupCall&& other) noexcept; ToxGroupCall(ToxGroupCall&& other) = delete;
~ToxGroupCall(); ~ToxGroupCall();
ToxGroupCall& operator=(ToxGroupCall&& other) noexcept; ToxGroupCall& operator=(ToxGroupCall&& other) = delete;
void removePeer(ToxPk peerId); void removePeer(ToxPk peerId);
void addPeer(ToxPk peerId); void addPeer(ToxPk peerId);