From 512dc8de2d998c71f713703cf73fc2c81cd7ce8a Mon Sep 17 00:00:00 2001 From: tux3 Date: Sun, 27 Sep 2015 19:59:26 +0200 Subject: [PATCH] Implement basic call logic We can now make New AV calls, but without any audio/video. Just opening a link. --- src/audio/audio.cpp | 6 +- src/core/core.cpp | 22 +- src/core/core.h | 18 +- src/core/coreav.cpp | 284 ++++++++++++++--------- src/core/coreav.h | 112 ++++++--- src/nexus.cpp | 4 +- src/video/corevideosource.h | 1 + src/widget/form/chatform.cpp | 64 +++-- src/widget/form/chatform.h | 37 ++- src/widget/form/groupchatform.cpp | 20 +- src/widget/form/settings/generalform.cpp | 2 +- src/widget/widget.cpp | 31 +-- 12 files changed, 341 insertions(+), 260 deletions(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index c980b4530..54a3faea9 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -122,8 +122,6 @@ void Audio::setOutputVolume(qreal volume) for (const ToxCall& call : CoreAV::calls) { - if (!call.active) - continue; alSourcef(call.alSource, AL_GAIN, outputVolume); } } @@ -214,7 +212,7 @@ void Audio::openInput(const QString& inDevDescr) Core* core = Core::getInstance(); if (core) - CoreAV::resetCallSources(); // Force to regen each group call's sources + core->getAv()->resetCallSources(); // Force to regen each group call's sources // Restart the capture if necessary if (alInDev) @@ -272,7 +270,7 @@ bool Audio::openOutput(const QString &outDevDescr) Core* core = Core::getInstance(); if (core) - CoreAV::resetCallSources(); // Force to regen each group call's sources + core->getAv()->resetCallSources(); // Force to regen each group call's sources return true; } diff --git a/src/core/core.cpp b/src/core/core.cpp index 23c036045..008529c09 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -61,7 +61,7 @@ QThread* Core::coreThread{nullptr}; #define MAX_GROUP_MESSAGE_LEN 1024 Core::Core(QThread *CoreThread, Profile& profile) : - tox(nullptr), toxav(nullptr), av(new CoreAV), profile(profile), ready{false} + tox(nullptr), av(nullptr), profile(profile), ready{false} { coreThread = CoreThread; @@ -77,10 +77,10 @@ Core::Core(QThread *CoreThread, Profile& profile) : void Core::deadifyTox() { - if (toxav) + if (av) { - toxav_kill(toxav); - toxav = nullptr; + delete av; + av = nullptr; } if (tox) { @@ -106,8 +106,6 @@ Core::~Core() coreThread->wait(500); } - delete av; - deadifyTox(); Audio& audio = Audio::getInstance(); @@ -120,7 +118,7 @@ Core* Core::getInstance() return Nexus::getCore(); } -const CoreAV *Core::getAv() const +CoreAV *Core::getAv() { return av; } @@ -223,8 +221,8 @@ void Core::makeTox(QByteArray savedata) return; } - toxav = toxav_new(tox, nullptr); - if (toxav == nullptr) + av = new CoreAV(tox); + if (av->getToxAv() == nullptr) { qCritical() << "Toxav core failed to start"; emit failedToStart(); @@ -350,7 +348,7 @@ void Core::process() static int tolerance = CORE_DISCONNECT_TOLERANCE; tox_iterate(tox); - toxav_iterate(toxav); ///< TODO: This is best called in a separate thread, as per the doc. + av->process(); #ifdef DEBUG //we want to see the debug messages immediately @@ -367,7 +365,7 @@ void Core::process() tolerance = 3*CORE_DISCONNECT_TOLERANCE; } - unsigned sleeptime = qMin(tox_iteration_interval(tox), toxav_iteration_interval(toxav)); + unsigned sleeptime = qMin(tox_iteration_interval(tox), toxav_iteration_interval(av->getToxAv())); sleeptime = qMin(sleeptime, CoreFile::corefileIterationInterval()); toxTimer->start(sleeptime); } @@ -1196,7 +1194,7 @@ QString Core::getPeerName(const ToxId& id) const bool Core::isReady() { - return toxav && tox && ready; + return av && av->getToxAv() && tox && ready; } void Core::setNospam(uint32_t nospam) diff --git a/src/core/core.h b/src/core/core.h index d13fc9c57..388ef3946 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -47,7 +47,7 @@ class Core : public QObject public: explicit Core(QThread* coreThread, Profile& profile); static Core* getInstance(); ///< Returns the global widget's Core instance - const CoreAV* getAv() const; + CoreAV* getAv(); ~Core(); static const QString TOX_EXT; @@ -192,21 +192,6 @@ signals: void fileSendFailed(uint32_t friendId, const QString& fname); - void avInvite(uint32_t friendId, int callIndex, bool video); - void avStart(uint32_t friendId, int callIndex, bool video); - void avCancel(uint32_t friendId, int callIndex); - void avEnd(uint32_t friendId, int callIndex); - void avRinging(uint32_t friendId, int callIndex, bool video); - void avStarting(uint32_t friendId, int callIndex, bool video); - void avEnding(uint32_t friendId, int callIndex); - void avRequestTimeout(uint32_t friendId, int callIndex); - void avPeerTimeout(uint32_t friendId, int callIndex); - void avMediaChange(uint32_t friendId, int callIndex, bool videoEnabled); - void avCallFailed(uint32_t friendId); - void avRejected(uint32_t friendId, int callIndex); - - void videoFrameReceived(vpx_image* frame); - private: static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage, size_t cMessageSize, void* core); @@ -245,7 +230,6 @@ private slots: private: Tox* tox; - ToxAV* toxav; CoreAV* av; QTimer *toxTimer; Profile& profile; diff --git a/src/core/coreav.cpp b/src/core/coreav.cpp index 4f215c6e6..7129c3c8a 100644 --- a/src/core/coreav.cpp +++ b/src/core/coreav.cpp @@ -32,132 +32,140 @@ #include #include -QVector CoreAV::calls; +QHash CoreAV::calls; QHash CoreAV::groupCalls; -#ifdef QTOX_FILTER_AUDIO -QVector CoreAV::filterer; -#endif -CoreAV::~CoreAV() +ToxCall::ToxCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av) + : sendAudioTimer{new QTimer}, friendNum{FriendNum}, + muteMic{false}, muteVol{false}, + videoEnabled{VideoEnabled}, + alSource{0}, videoSource{nullptr}, + state{static_cast(0)} { - for (ToxCall call : calls) - { - if (!call.active) - continue; - hangupCall(call.callId); - } -} - -bool CoreAV::anyActiveCalls() -{ - for (auto& call : calls) - { - if (call.active) - return true; - } - return false; -} - -void CoreAV::prepareCall(uint32_t friendId, int32_t callId, ToxAV* toxav, bool videoEnabled) -{ - qDebug() << QString("preparing call %1").arg(callId); - - calls[callId].callId = callId; - calls[callId].friendId = friendId; - calls[callId].muteMic = false; - calls[callId].muteVol = false; - // the following three lines are also now redundant from startCall, but are - // necessary there for outbound and here for inbound - calls[callId].videoEnabled = videoEnabled; - - // Audio Audio::getInstance().subscribeInput(); + sendAudioTimer->setInterval(5); + sendAudioTimer->setSingleShot(true); + QObject::connect(sendAudioTimer, &QTimer::timeout, [=,&av](){av.sendCallAudio(friendNum);}); + sendAudioTimer->start(); - // Go - calls[callId].active = true; - calls[callId].sendAudioTimer->setInterval(5); - calls[callId].sendAudioTimer->setSingleShot(true); - connect(calls[callId].sendAudioTimer, &QTimer::timeout, [=](){sendCallAudio(callId,toxav);}); - calls[callId].sendAudioTimer->start(); - - if (calls[callId].videoEnabled) + if (videoEnabled) { - calls[callId].videoSource = new CoreVideoSource; + videoSource = new CoreVideoSource; CameraSource& source = CameraSource::getInstance(); source.subscribe(); - connect(&source, &VideoSource::frameAvailable, - [=](std::shared_ptr frame){sendCallVideo(callId,toxav,frame);}); + QObject::connect(&source, &VideoSource::frameAvailable, + [=,&av](std::shared_ptr frame){av.sendCallVideo(friendNum,frame);}); } + #ifdef QTOX_FILTER_AUDIO if (Settings::getInstance().getFilterAudio()) { - filterer[callId] = new AudioFilterer(); - filterer[callId]->startFilter(48000); + filterer = new AudioFilterer(); + filterer->startFilter(48000); } else { - delete filterer[callId]; - filterer[callId] = nullptr; + filterer = nullptr; } #endif } -void CoreAV::answerCall(int32_t callId) +ToxCall::~ToxCall() { - -} - -void CoreAV::hangupCall(int32_t callId) -{ - qDebug() << QString("hanging up call %1").arg(callId); - calls[callId].active = false; -} - -void CoreAV::rejectCall(int32_t callId) -{ - qDebug() << QString("rejecting call %1").arg(callId); - calls[callId].active = false; -} - -void CoreAV::startCall(uint32_t friendId, bool video) -{ - -} - -void CoreAV::cancelCall(int32_t callId, uint32_t friendId) -{ - qDebug() << QString("Cancelling call with %1").arg(friendId); - calls[callId].active = false; -} - -void CoreAV::cleanupCall(int32_t callId) -{ - assert(calls[callId].active); - qDebug() << QString("cleaning up call %1").arg(callId); - calls[callId].active = false; - disconnect(calls[callId].sendAudioTimer,0,0,0); - calls[callId].sendAudioTimer->stop(); - - if (calls[callId].videoEnabled) + QObject::disconnect(sendAudioTimer, nullptr, nullptr, nullptr); + sendAudioTimer->stop(); + if (videoEnabled) { CameraSource::getInstance().unsubscribe(); - if (calls[callId].videoSource) + if (videoSource) { - calls[callId].videoSource->setDeleteOnClose(true); - calls[callId].videoSource = nullptr; + videoSource->setDeleteOnClose(true); + videoSource = nullptr; } } Audio::getInstance().unsubscribeInput(); - //toxav_kill_transmission(Core::getInstance()->toxav, callId); +} + +CoreAV::CoreAV(Tox *tox) +{ + toxav = toxav_new(tox, nullptr); + + toxav_callback_call(toxav, CoreAV::callCallback, this); + toxav_callback_call_state(toxav, CoreAV::stateCallback, this); + toxav_callback_audio_bit_rate_status(toxav, CoreAV::audioBitrateCallback, this); + toxav_callback_video_bit_rate_status(toxav, CoreAV::videoBitrateCallback, this); + toxav_callback_audio_receive_frame(toxav, CoreAV::audioFrameCallback, this); + toxav_callback_video_receive_frame(toxav, CoreAV::videoFrameCallback, this); +} + +CoreAV::~CoreAV() +{ + for (ToxCall call : calls) + cancelCall(call.friendNum); + toxav_kill(toxav); +} + +const ToxAV *CoreAV::getToxAv() const +{ + return toxav; +} + +void CoreAV::process() +{ + toxav_iterate(toxav); +} + +bool CoreAV::anyActiveCalls() +{ + return !calls.isEmpty(); +} + +void CoreAV::answerCall(uint32_t friendNum) +{ + qDebug() << QString("answering call %1").arg(friendNum); + assert(calls.contains(friendNum)); + TOXAV_ERR_ANSWER err; + if (toxav_answer(toxav, friendNum, AUDIO_DEFAULT_BITRATE, VIDEO_DEFAULT_BITRATE, &err)) + { + emit avStart(friendNum, calls[friendNum].videoEnabled); + } + else + { + qWarning() << "Failed to answer call with error"<pushFrame(img); } -void CoreAV::sendCallVideo(int32_t callId, ToxAV* toxav, std::shared_ptr vframe) +void CoreAV::sendCallVideo(uint32_t callId, std::shared_ptr vframe) { - if (!calls[callId].active || !calls[callId].videoEnabled) + if (!calls.contains(callId) || !calls[callId].videoEnabled + || !(calls[callId].state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V)) return; // This frame shares vframe's buffers, we don't call vpx_img_free but just delete it @@ -262,15 +271,15 @@ void CoreAV::sendCallVideo(int32_t callId, ToxAV* toxav, std::shared_ptrtoxav; - groupCalls[groupId].sendAudioTimer = new QTimer(); groupCalls[groupId].active = true; groupCalls[groupId].sendAudioTimer->setInterval(5); @@ -412,17 +419,17 @@ void CoreAV::enableGroupCallVol(int groupId) groupCalls[groupId].muteVol = false; } -bool CoreAV::isGroupCallMicEnabled(int groupId) +bool CoreAV::isGroupCallMicEnabled(int groupId) const { return !groupCalls[groupId].muteMic; } -bool CoreAV::isGroupCallVolEnabled(int groupId) +bool CoreAV::isGroupCallVolEnabled(int groupId) const { return !groupCalls[groupId].muteVol; } -bool CoreAV::isGroupAvEnabled(int groupId) +bool CoreAV::isGroupAvEnabled(int groupId) const { return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV; } @@ -438,7 +445,7 @@ void CoreAV::resetCallSources() for (ToxCall& call : calls) { - if (call.active && call.alSource) + if (call.alSource) { ALuint tmp = call.alSource; call.alSource = 0; @@ -448,3 +455,60 @@ void CoreAV::resetCallSources() } } } + +void CoreAV::callCallback(ToxAV*, uint32_t friendNum, bool, bool video, void *_self) +{ + qWarning() << "RECEIVED CALL"; + CoreAV* self = static_cast(_self); + calls.insert(friendNum, {friendNum, video, *self}); + emit reinterpret_cast(self)->avInvite(friendNum, video); +} + +void CoreAV::stateCallback(ToxAV *toxAV, uint32_t friendNum, uint32_t state, void *_self) +{ + qWarning() << "STATE IS "<(_self); + + assert(self->calls.contains(friendNum)); + ToxCall& call = self->calls[friendNum]; + + if (state & TOXAV_FRIEND_CALL_STATE_ERROR) + { + qWarning() << "Call with friend"<avCallFailed(friendNum); + } + else if (state & TOXAV_FRIEND_CALL_STATE_FINISHED) + { + calls.remove(friendNum); + emit self->avEnd(friendNum); + } + else + { + // If our state was null, we were ringing and the call just started + if (!call.state && state) + emit self->avStart(friendNum, call.videoEnabled); + + call.state = static_cast(state); + } +} + +void CoreAV::audioBitrateCallback(ToxAV *toxAV, uint32_t friendNum, bool stable, uint32_t rate, void *self) +{ + qWarning() << "AUDIO BITRATE IS "< #include #include +#include #include #if defined(__APPLE__) && defined(__MACH__) @@ -43,19 +44,26 @@ class CoreVideoSource; class CameraSource; class VideoSource; class VideoFrame; +class CoreAV; struct vpx_image; struct ToxCall { + ToxCall() = default; + ToxCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av); + ~ToxCall(); + QTimer *sendAudioTimer; - int32_t callId; - uint32_t friendId; - bool videoEnabled; - bool active; + uint32_t friendNum; bool muteMic; bool muteVol; + bool videoEnabled; ///< True if our user asked for a video call, sending and recving ALuint alSource; CoreVideoSource* videoSource; + TOXAV_FRIEND_CALL_STATE state; ///< State of the peer (not ours!) +#ifdef QTOX_FILTER_AUDIO + AudioFilterer* filterer; +#endif }; struct ToxGroupCall @@ -73,49 +81,79 @@ class CoreAV : public QThread Q_OBJECT public: - CoreAV() = default; + CoreAV(Tox* tox); ~CoreAV(); - static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active) - static void prepareCall(uint32_t friendId, int callId, ToxAV *toxav, bool videoEnabled); - static void cleanupCall(int callId); - static void playCallAudio(void *toxav, int32_t callId, const int16_t *data, + const ToxAV* getToxAv() const; + + void process(); + + bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active) + void prepareCall(uint32_t friendId, ToxAV *toxav, bool videoEnabled); + void cleanupCall(uint32_t friendId); + void playCallAudio(void *toxav, int32_t callId, const int16_t *data, uint16_t samples, void *user_data); // Callback - static void sendCallAudio(int callId, ToxAV* toxav); - static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, + void sendCallAudio(uint32_t friendId); + void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate); - static void playCallVideo(void *toxav, int32_t callId, const vpx_image* img, void *user_data); - static void sendCallVideo(int callId, ToxAV* toxav, std::shared_ptr frame); - static void sendGroupCallAudio(int groupId, ToxAV* toxav); + void playCallVideo(void *toxav, int32_t callId, const vpx_image* img, void *user_data); + void sendCallVideo(uint32_t friendId, std::shared_ptr frame); + void sendGroupCallAudio(int groupId, ToxAV* toxav); - static VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source - static void resetCallSources(); ///< Forces to regenerate each call's audio sources + VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source + void resetCallSources(); ///< Forces to regenerate each call's audio sources - static void joinGroupCall(int groupId); ///< Starts a call in an existing AV groupchat. Call from the GUI thread. - static void leaveGroupCall(int groupId); ///< Will not leave the group, just stop the call. Call from the GUI thread. - static void disableGroupCallMic(int groupId); - static void disableGroupCallVol(int groupId); - static void enableGroupCallMic(int groupId); - static void enableGroupCallVol(int groupId); - static bool isGroupCallMicEnabled(int groupId); - static bool isGroupCallVolEnabled(int groupId); - static bool isGroupAvEnabled(int groupId); ///< True for AV groups, false for text-only groups + void joinGroupCall(int groupId); ///< Starts a call in an existing AV groupchat. Call from the GUI thread. + void leaveGroupCall(int groupId); ///< Will not leave the group, just stop the call. Call from the GUI thread. + void disableGroupCallMic(int groupId); + void disableGroupCallVol(int groupId); + void enableGroupCallMic(int groupId); + void enableGroupCallVol(int groupId); + bool isGroupCallMicEnabled(int groupId) const; + bool isGroupCallVolEnabled(int groupId) const; + bool isGroupAvEnabled(int groupId) const; ///< True for AV groups, false for text-only groups -public slots: - static void answerCall(int callId); - static void rejectCall(int callId); - static void hangupCall(int callId); - static void startCall(uint32_t friendId, bool video=false); - static void cancelCall(int callId, uint32_t friendId); + void startCall(uint32_t friendId, bool video=false); + void answerCall(uint32_t friendId); + void cancelCall(uint32_t friendId); - static void micMuteToggle(int callId); - static void volMuteToggle(int callId); + void micMuteToggle(uint32_t friendId); + void volMuteToggle(uint32_t friendId); + +signals: + void avInvite(uint32_t friendId, bool video); + void avStart(uint32_t friendId, bool video); + void avCancel(uint32_t friendId); + void avEnd(uint32_t friendId); + void avRinging(uint32_t friendId, bool video); + void avStarting(uint32_t friendId, bool video); + void avEnding(uint32_t friendId); + void avRequestTimeout(uint32_t friendId); + void avPeerTimeout(uint32_t friendId); + void avMediaChange(uint32_t friendId, bool videoEnabled); + void avCallFailed(uint32_t friendId); + void avRejected(uint32_t friendId); + + void videoFrameReceived(vpx_image* frame); private: - static QVector calls; -#ifdef QTOX_FILTER_AUDIO - static QVector filterer; -#endif + static void callCallback(ToxAV *toxAV, uint32_t friendNum, bool audio, bool video, void* self); + static void stateCallback(ToxAV *toxAV, uint32_t friendNum, uint32_t state, void* self); + static void audioBitrateCallback(ToxAV *toxAV, uint32_t friendNum, bool stable, uint32_t rate, void* self); + static void videoBitrateCallback(ToxAV *toxAV, uint32_t friendNum, bool stable, uint32_t rate, void* self); + static void audioFrameCallback(ToxAV *toxAV, uint32_t friendNum, const int16_t *pcm, size_t sampleCount, + uint8_t channels, uint32_t samplingRate, void* self); + static void videoFrameCallback(ToxAV *toxAV, uint32_t friendNum, uint16_t w, uint16_t h, + const uint8_t *y, const uint8_t *u, const uint8_t *v, + int32_t ystride, int32_t ustride, int32_t vstride, void* self); + +private: + static constexpr uint32_t AUDIO_DEFAULT_BITRATE = 64; ///< In kb/s. More than enough for Opus. + static constexpr uint32_t VIDEO_DEFAULT_BITRATE = 384; ///< Picked at random by fair dice roll. + +private: + ToxAV* toxav; + static QHash calls; static QHash groupCalls; // Maps group IDs to ToxGroupCalls friend class Audio; diff --git a/src/nexus.cpp b/src/nexus.cpp index 0380a882b..6e65c272f 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -21,6 +21,7 @@ #include "nexus.h" #include "src/persistence/profile.h" #include "src/core/core.h" +#include "src/core/coreav.h" #include "persistence/settings.h" #include "video/camerasource.h" #include "widget/gui.h" @@ -189,6 +190,7 @@ void Nexus::showMainGUI() // Connections Core* core = profile->getCore(); + CoreAV* coreav = core->getAv(); #ifdef Q_OS_ANDROID connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected); connect(core, &Core::disconnected, androidgui, &AndroidGUI::onDisconnected); @@ -227,7 +229,7 @@ void Nexus::showMainGUI() connect(core, &Core::groupTitleChanged, widget, &Widget::onGroupTitleChanged); connect(core, &Core::groupPeerAudioPlaying, widget, &Widget::onGroupPeerAudioPlaying); connect(core, &Core::emptyGroupCreated, widget, &Widget::onEmptyGroupCreated); - connect(core, &Core::avInvite, widget, &Widget::playRingtone); + connect(coreav, &CoreAV::avInvite, widget, &Widget::playRingtone); connect(core, &Core::friendTypingChanged, widget, &Widget::onFriendTypingChanged); connect(core, &Core::messageSentResult, widget, &Widget::onMessageSendResult); diff --git a/src/video/corevideosource.h b/src/video/corevideosource.h index 028763ba5..9a290c38d 100644 --- a/src/video/corevideosource.h +++ b/src/video/corevideosource.h @@ -50,6 +50,7 @@ private: std::atomic_bool biglock; ///< Fast lock friend class CoreAV; +friend struct ToxCall; }; #endif // COREVIDEOSOURCE_H diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 12488af13..e08cf4053 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -63,7 +63,7 @@ ChatForm::ChatForm(Friend* chatFriend) : f(chatFriend) - , callId{0}, isTyping{false} + , isTyping{false} { nameLabel->setText(f->getDisplayedName()); @@ -251,14 +251,13 @@ void ChatForm::onFileRecvRequest(ToxFile file) Widget::getInstance()->updateFriendActivity(f); } -void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) +void ChatForm::onAvInvite(uint32_t FriendId, bool video) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvInvite, callId: " << CallId; + qDebug() << "onAvInvite"; - callId = CallId; callButton->disconnect(); videoButton->disconnect(); if (video) @@ -302,16 +301,15 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) Widget::getInstance()->newFriendMessageAlert(FriendId); } -void ChatForm::onAvStart(uint32_t FriendId, int CallId, bool video) +void ChatForm::onAvStart(uint32_t FriendId, bool video) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvStart, callId: " << CallId; + qDebug() << "onAvStart"; audioInputFlag = true; audioOutputFlag = true; - callId = CallId; callButton->disconnect(); videoButton->disconnect(); @@ -354,12 +352,12 @@ void ChatForm::onAvStart(uint32_t FriendId, int CallId, bool video) startCounter(); } -void ChatForm::onAvCancel(uint32_t FriendId, int CallId) +void ChatForm::onAvCancel(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvCancel, callId: " << CallId; + qDebug() << "onAvCancel"; delete callConfirm; callConfirm = nullptr; @@ -374,14 +372,13 @@ void ChatForm::onAvCancel(uint32_t FriendId, int CallId) QDateTime::currentDateTime()); } -void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video) +void ChatForm::onAvRinging(uint32_t FriendId, bool video) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvRinging, callId: " << CallId; + qDebug() << "onAvRinging"; - callId = CallId; callButton->disconnect(); videoButton->disconnect(); if (video) @@ -414,14 +411,12 @@ void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video) Widget::getInstance()->updateFriendActivity(f); } -void ChatForm::onAvStarting(uint32_t FriendId, int CallId, bool video) +void ChatForm::onAvStarting(uint32_t FriendId, bool video) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvStarting, callId:" << CallId; - - callId = CallId; + qDebug() << "onAvStarting"; callButton->disconnect(); videoButton->disconnect(); @@ -451,12 +446,12 @@ void ChatForm::onAvStarting(uint32_t FriendId, int CallId, bool video) startCounter(); } -void ChatForm::onAvEnding(uint32_t FriendId, int CallId) +void ChatForm::onAvEnding(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvEnding, callId: " << CallId; + qDebug() << "onAvEnding"; delete callConfirm; callConfirm = nullptr; @@ -467,12 +462,12 @@ void ChatForm::onAvEnding(uint32_t FriendId, int CallId) hideNetcam(); } -void ChatForm::onAvEnd(uint32_t FriendId, int CallId) +void ChatForm::onAvEnd(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvEnd, callId: " << CallId; + qDebug() << "onAvEnd"; delete callConfirm; callConfirm = nullptr; @@ -482,12 +477,12 @@ void ChatForm::onAvEnd(uint32_t FriendId, int CallId) hideNetcam(); } -void ChatForm::onAvRequestTimeout(uint32_t FriendId, int CallId) +void ChatForm::onAvRequestTimeout(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; - qDebug() << "onAvRequestTimeout, callId: " << CallId; + qDebug() << "onAvRequestTimeout"; delete callConfirm; callConfirm = nullptr; @@ -498,7 +493,7 @@ void ChatForm::onAvRequestTimeout(uint32_t FriendId, int CallId) hideNetcam(); } -void ChatForm::onAvPeerTimeout(uint32_t FriendId, int) +void ChatForm::onAvPeerTimeout(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; @@ -514,7 +509,7 @@ void ChatForm::onAvPeerTimeout(uint32_t FriendId, int) hideNetcam(); } -void ChatForm::onAvRejected(uint32_t FriendId, int) +void ChatForm::onAvRejected(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; @@ -533,12 +528,12 @@ void ChatForm::onAvRejected(uint32_t FriendId, int) hideNetcam(); } -void ChatForm::onAvMediaChange(uint32_t FriendId, int CallId, bool video) +void ChatForm::onAvMediaChange(uint32_t FriendId, bool video) { - if (FriendId != f->getFriendID() || CallId != callId) + if (FriendId != f->getFriendID()) return; - qDebug() << "onAvMediaChange, callId: " << CallId; + qDebug() << "onAvMediaChange"; if (video) showNetcam(); @@ -558,7 +553,7 @@ void ChatForm::onAnswerCallTriggered() audioInputFlag = true; audioOutputFlag = true; - emit answerCall(callId); + emit answerCall(f->getFriendID()); } void ChatForm::onHangupCallTriggered() @@ -571,8 +566,9 @@ void ChatForm::onHangupCallTriggered() audioInputFlag = false; audioOutputFlag = false; - emit hangupCall(callId); + emit hangupCall(f->getFriendID()); + stopCounter(); enableCallButtons(); } @@ -588,7 +584,7 @@ void ChatForm::onRejectCallTriggered() audioInputFlag = false; audioOutputFlag = false; - emit rejectCall(callId); + emit rejectCall(f->getFriendID()); enableCallButtons(); } @@ -635,7 +631,7 @@ void ChatForm::onCancelCallTriggered() enableCallButtons(); hideNetcam(); - emit cancelCall(callId, f->getFriendID()); + emit cancelCall(f->getFriendID()); } void ChatForm::enableCallButtons() @@ -701,7 +697,7 @@ void ChatForm::onMicMuteToggle() { if (audioInputFlag == true) { - emit micMuteToggle(callId); + emit micMuteToggle(f->getFriendID()); if (micButton->objectName() == "red") { micButton->setObjectName("green"); @@ -721,7 +717,7 @@ void ChatForm::onVolMuteToggle() { if (audioOutputFlag == true) { - emit volMuteToggle(callId); + emit volMuteToggle(f->getFriendID()); if (volButton->objectName() == "red") { volButton->setObjectName("green"); @@ -757,7 +753,7 @@ GenericNetCamView *ChatForm::createNetcam() { qDebug() << "creating netcam"; NetCamView* view = new NetCamView(f->getFriendID(), this); - view->show(CoreAV::getVideoSourceFromCall(callId), f->getDisplayedName()); + view->show(Core::getInstance()->getAv()->getVideoSourceFromCall(f->getFriendID()), f->getDisplayedName()); return view; } diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index c12ad3511..11081795e 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -52,30 +52,30 @@ public: signals: void sendFile(uint32_t friendId, QString, QString, long long); - void startCall(uint32_t FriendId, bool video); - void answerCall(int callId); - void hangupCall(int callId); - void cancelCall(int callId, uint32_t FriendId); - void rejectCall(int callId); - void micMuteToggle(int callId); - void volMuteToggle(int callId); + void startCall(uint32_t friendId, bool video); + void answerCall(uint32_t friendId); + void hangupCall(uint32_t friendId); + void cancelCall(uint32_t friendId); + void rejectCall(uint32_t friendId); + void micMuteToggle(uint32_t friendId); + void volMuteToggle(uint32_t friendId); void aliasChanged(const QString& alias); public slots: void startFileSend(ToxFile file); void onFileRecvRequest(ToxFile file); - void onAvInvite(uint32_t FriendId, int CallId, bool video); - void onAvStart(uint32_t FriendId, int CallId, bool video); - void onAvCancel(uint32_t FriendId, int CallId); - void onAvEnd(uint32_t FriendId, int CallId); - void onAvRinging(uint32_t FriendId, int CallId, bool video); - void onAvStarting(uint32_t FriendId, int CallId, bool video); - void onAvEnding(uint32_t FriendId, int CallId); - void onAvRequestTimeout(uint32_t FriendId, int CallId); - void onAvPeerTimeout(uint32_t FriendId, int CallId); - void onAvMediaChange(uint32_t FriendId, int CallId, bool video); + void onAvInvite(uint32_t FriendId, bool video); + void onAvStart(uint32_t FriendId, bool video); + void onAvCancel(uint32_t FriendId); + void onAvEnd(uint32_t FriendId); + void onAvRinging(uint32_t FriendId, bool video); + void onAvStarting(uint32_t FriendId, bool video); + void onAvEnding(uint32_t FriendId); + void onAvRequestTimeout(uint32_t FriendId); + void onAvPeerTimeout(uint32_t FriendId); + void onAvMediaChange(uint32_t FriendId, bool video); void onAvCallFailed(uint32_t FriendId); - void onAvRejected(uint32_t FriendId, int CallId); + void onAvRejected(uint32_t FriendId); void onMicMuteToggle(); void onVolMuteToggle(); void onAvatarChange(uint32_t FriendId, const QPixmap& pic); @@ -114,7 +114,6 @@ protected: private: Friend* f; CroppingLabel *statusMessageLabel; - int callId; QLabel *callDuration; QTimer *callDurationTimer; QTimer typingTimer; diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 6e0ff4ad7..51e6c6114 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -283,13 +283,13 @@ void GroupChatForm::onMicMuteToggle() { if (micButton->objectName() == "red") { - CoreAV::enableGroupCallMic(group->getGroupId()); + Core::getInstance()->getAv()->enableGroupCallMic(group->getGroupId()); micButton->setObjectName("green"); micButton->setToolTip(tr("Mute microphone")); } else { - CoreAV::disableGroupCallMic(group->getGroupId()); + Core::getInstance()->getAv()->disableGroupCallMic(group->getGroupId()); micButton->setObjectName("red"); micButton->setToolTip(tr("Unmute microphone")); } @@ -304,13 +304,13 @@ void GroupChatForm::onVolMuteToggle() { if (volButton->objectName() == "red") { - CoreAV::enableGroupCallVol(group->getGroupId()); + Core::getInstance()->getAv()->enableGroupCallVol(group->getGroupId()); volButton->setObjectName("green"); volButton->setToolTip(tr("Mute call")); } else { - CoreAV::disableGroupCallVol(group->getGroupId()); + Core::getInstance()->getAv()->disableGroupCallVol(group->getGroupId()); volButton->setObjectName("red"); volButton->setToolTip(tr("Unmute call")); } @@ -323,7 +323,7 @@ void GroupChatForm::onCallClicked() { if (!inCall) { - CoreAV::joinGroupCall(group->getGroupId()); + Core::getInstance()->getAv()->joinGroupCall(group->getGroupId()); audioInputFlag = true; audioOutputFlag = true; callButton->setObjectName("red"); @@ -340,7 +340,7 @@ void GroupChatForm::onCallClicked() } else { - CoreAV::leaveGroupCall(group->getGroupId()); + Core::getInstance()->getAv()->leaveGroupCall(group->getGroupId()); audioInputFlag = false; audioOutputFlag = false; callButton->setObjectName("green"); @@ -376,9 +376,9 @@ void GroupChatForm::keyPressEvent(QKeyEvent* ev) // Push to talk (CTRL+P) if (ev->key() == Qt::Key_P && (ev->modifiers() & Qt::ControlModifier) && inCall) { - if (!CoreAV::isGroupCallMicEnabled(group->getGroupId())) + if (!Core::getInstance()->getAv()->isGroupCallMicEnabled(group->getGroupId())) { - CoreAV::enableGroupCallMic(group->getGroupId()); + Core::getInstance()->getAv()->enableGroupCallMic(group->getGroupId()); micButton->setObjectName("green"); micButton->style()->polish(micButton); Style::repolish(micButton); @@ -394,9 +394,9 @@ void GroupChatForm::keyReleaseEvent(QKeyEvent* ev) // Push to talk (CTRL+P) if (ev->key() == Qt::Key_P && (ev->modifiers() & Qt::ControlModifier) && inCall) { - if (CoreAV::isGroupCallMicEnabled(group->getGroupId())) + if (Core::getInstance()->getAv()->isGroupCallMicEnabled(group->getGroupId())) { - CoreAV::disableGroupCallMic(group->getGroupId()); + Core::getInstance()->getAv()->disableGroupCallMic(group->getGroupId()); micButton->setObjectName("red"); micButton->style()->polish(micButton); Style::repolish(micButton); diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp index e1c81108e..7d33fac7e 100644 --- a/src/widget/form/settings/generalform.cpp +++ b/src/widget/form/settings/generalform.cpp @@ -359,7 +359,7 @@ void GeneralForm::onUseProxyUpdated() void GeneralForm::onReconnectClicked() { - if (CoreAV::anyActiveCalls()) + if (Core::getInstance()->getAv()->anyActiveCalls()) { QMessageBox::warning(this, tr("Call active", "popup title"), tr("You can't disconnect while a call is active!", "popup text")); diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 8c7da5139..0a6470707 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -882,6 +882,7 @@ void Widget::addFriend(int friendId, const QString &userId) contactListWidget->addFriendWidget(newfriend->getFriendWidget(),Status::Offline,Settings::getInstance().getFriendCircleID(newfriend->getToxId())); Core* core = Nexus::getCore(); + CoreAV* coreav = core->getAv(); connect(newfriend, &Friend::displayedNameChanged, this, &Widget::onFriendDisplayChanged); connect(settingsWidget, &SettingsWidget::compactToggled, newfriend->getFriendWidget(), &GenericChatroomWidget::compactChange); connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*,bool)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*,bool))); @@ -892,26 +893,26 @@ void Widget::addFriend(int friendId, const QString &userId) connect(newfriend->getChatForm(), &GenericChatForm::sendAction, core, &Core::sendAction); connect(newfriend->getChatForm(), &ChatForm::sendFile, core, &Core::sendFile); connect(newfriend->getChatForm(), &ChatForm::answerCall, core->getAv(), &CoreAV::answerCall); - connect(newfriend->getChatForm(), &ChatForm::hangupCall, core->getAv(), &CoreAV::hangupCall); - connect(newfriend->getChatForm(), &ChatForm::rejectCall, core->getAv(), &CoreAV::rejectCall); + connect(newfriend->getChatForm(), &ChatForm::hangupCall, core->getAv(), &CoreAV::cancelCall); + connect(newfriend->getChatForm(), &ChatForm::rejectCall, core->getAv(), &CoreAV::cancelCall); connect(newfriend->getChatForm(), &ChatForm::startCall, core->getAv(), &CoreAV::startCall); connect(newfriend->getChatForm(), &ChatForm::cancelCall, core->getAv(), &CoreAV::cancelCall); connect(newfriend->getChatForm(), &ChatForm::micMuteToggle, core->getAv(), &CoreAV::micMuteToggle); connect(newfriend->getChatForm(), &ChatForm::volMuteToggle, core->getAv(), &CoreAV::volMuteToggle); connect(newfriend->getChatForm(), &ChatForm::aliasChanged, newfriend->getFriendWidget(), &FriendWidget::setAlias); connect(core, &Core::fileReceiveRequested, newfriend->getChatForm(), &ChatForm::onFileRecvRequest); - connect(core, &Core::avInvite, newfriend->getChatForm(), &ChatForm::onAvInvite); - connect(core, &Core::avStart, newfriend->getChatForm(), &ChatForm::onAvStart); - connect(core, &Core::avCancel, newfriend->getChatForm(), &ChatForm::onAvCancel); - connect(core, &Core::avEnd, newfriend->getChatForm(), &ChatForm::onAvEnd); - connect(core, &Core::avRinging, newfriend->getChatForm(), &ChatForm::onAvRinging); - connect(core, &Core::avStarting, newfriend->getChatForm(), &ChatForm::onAvStarting); - connect(core, &Core::avEnding, newfriend->getChatForm(), &ChatForm::onAvEnding); - connect(core, &Core::avRequestTimeout, newfriend->getChatForm(), &ChatForm::onAvRequestTimeout); - connect(core, &Core::avPeerTimeout, newfriend->getChatForm(), &ChatForm::onAvPeerTimeout); - connect(core, &Core::avMediaChange, newfriend->getChatForm(), &ChatForm::onAvMediaChange); - connect(core, &Core::avCallFailed, newfriend->getChatForm(), &ChatForm::onAvCallFailed); - connect(core, &Core::avRejected, newfriend->getChatForm(), &ChatForm::onAvRejected); + connect(coreav, &CoreAV::avInvite, newfriend->getChatForm(), &ChatForm::onAvInvite); + connect(coreav, &CoreAV::avStart, newfriend->getChatForm(), &ChatForm::onAvStart); + connect(coreav, &CoreAV::avCancel, newfriend->getChatForm(), &ChatForm::onAvCancel); + connect(coreav, &CoreAV::avEnd, newfriend->getChatForm(), &ChatForm::onAvEnd); + connect(coreav, &CoreAV::avRinging, newfriend->getChatForm(), &ChatForm::onAvRinging); + connect(coreav, &CoreAV::avStarting, newfriend->getChatForm(), &ChatForm::onAvStarting); + connect(coreav, &CoreAV::avEnding, newfriend->getChatForm(), &ChatForm::onAvEnding); + connect(coreav, &CoreAV::avRequestTimeout, newfriend->getChatForm(), &ChatForm::onAvRequestTimeout); + connect(coreav, &CoreAV::avPeerTimeout, newfriend->getChatForm(), &ChatForm::onAvPeerTimeout); + connect(coreav, &CoreAV::avMediaChange, newfriend->getChatForm(), &ChatForm::onAvMediaChange); + connect(coreav, &CoreAV::avCallFailed, newfriend->getChatForm(), &ChatForm::onAvCallFailed); + connect(coreav, &CoreAV::avRejected, newfriend->getChatForm(), &ChatForm::onAvRejected); connect(core, &Core::friendAvatarChanged, newfriend->getChatForm(), &ChatForm::onAvatarChange); connect(core, &Core::friendAvatarChanged, newfriend->getFriendWidget(), &FriendWidget::onAvatarChange); connect(core, &Core::friendAvatarRemoved, newfriend->getChatForm(), &ChatForm::onAvatarRemoved); @@ -1589,7 +1590,7 @@ Group *Widget::createGroup(int groupId) Core* core = Nexus::getCore(); QString groupName = QString("Groupchat #%1").arg(groupId); - Group* newgroup = GroupList::addGroup(groupId, groupName, CoreAV::isGroupAvEnabled(groupId)); + Group* newgroup = GroupList::addGroup(groupId, groupName, core->getAv()->isGroupAvEnabled(groupId)); contactListWidget->addGroupWidget(newgroup->getGroupWidget()); newgroup->getGroupWidget()->updateStatusLight();