mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Implement basic call logic
We can now make New AV calls, but without any audio/video. Just opening a link.
This commit is contained in:
parent
dbbc702c60
commit
512dc8de2d
|
@ -122,8 +122,6 @@ void Audio::setOutputVolume(qreal volume)
|
||||||
|
|
||||||
for (const ToxCall& call : CoreAV::calls)
|
for (const ToxCall& call : CoreAV::calls)
|
||||||
{
|
{
|
||||||
if (!call.active)
|
|
||||||
continue;
|
|
||||||
alSourcef(call.alSource, AL_GAIN, outputVolume);
|
alSourcef(call.alSource, AL_GAIN, outputVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,7 +212,7 @@ void Audio::openInput(const QString& inDevDescr)
|
||||||
|
|
||||||
Core* core = Core::getInstance();
|
Core* core = Core::getInstance();
|
||||||
if (core)
|
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
|
// Restart the capture if necessary
|
||||||
if (alInDev)
|
if (alInDev)
|
||||||
|
@ -272,7 +270,7 @@ bool Audio::openOutput(const QString &outDevDescr)
|
||||||
|
|
||||||
Core* core = Core::getInstance();
|
Core* core = Core::getInstance();
|
||||||
if (core)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ QThread* Core::coreThread{nullptr};
|
||||||
#define MAX_GROUP_MESSAGE_LEN 1024
|
#define MAX_GROUP_MESSAGE_LEN 1024
|
||||||
|
|
||||||
Core::Core(QThread *CoreThread, Profile& profile) :
|
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;
|
coreThread = CoreThread;
|
||||||
|
|
||||||
|
@ -77,10 +77,10 @@ Core::Core(QThread *CoreThread, Profile& profile) :
|
||||||
|
|
||||||
void Core::deadifyTox()
|
void Core::deadifyTox()
|
||||||
{
|
{
|
||||||
if (toxav)
|
if (av)
|
||||||
{
|
{
|
||||||
toxav_kill(toxav);
|
delete av;
|
||||||
toxav = nullptr;
|
av = nullptr;
|
||||||
}
|
}
|
||||||
if (tox)
|
if (tox)
|
||||||
{
|
{
|
||||||
|
@ -106,8 +106,6 @@ Core::~Core()
|
||||||
coreThread->wait(500);
|
coreThread->wait(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete av;
|
|
||||||
|
|
||||||
deadifyTox();
|
deadifyTox();
|
||||||
|
|
||||||
Audio& audio = Audio::getInstance();
|
Audio& audio = Audio::getInstance();
|
||||||
|
@ -120,7 +118,7 @@ Core* Core::getInstance()
|
||||||
return Nexus::getCore();
|
return Nexus::getCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoreAV *Core::getAv() const
|
CoreAV *Core::getAv()
|
||||||
{
|
{
|
||||||
return av;
|
return av;
|
||||||
}
|
}
|
||||||
|
@ -223,8 +221,8 @@ void Core::makeTox(QByteArray savedata)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
toxav = toxav_new(tox, nullptr);
|
av = new CoreAV(tox);
|
||||||
if (toxav == nullptr)
|
if (av->getToxAv() == nullptr)
|
||||||
{
|
{
|
||||||
qCritical() << "Toxav core failed to start";
|
qCritical() << "Toxav core failed to start";
|
||||||
emit failedToStart();
|
emit failedToStart();
|
||||||
|
@ -350,7 +348,7 @@ void Core::process()
|
||||||
|
|
||||||
static int tolerance = CORE_DISCONNECT_TOLERANCE;
|
static int tolerance = CORE_DISCONNECT_TOLERANCE;
|
||||||
tox_iterate(tox);
|
tox_iterate(tox);
|
||||||
toxav_iterate(toxav); ///< TODO: This is best called in a separate thread, as per the doc.
|
av->process();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
//we want to see the debug messages immediately
|
//we want to see the debug messages immediately
|
||||||
|
@ -367,7 +365,7 @@ void Core::process()
|
||||||
tolerance = 3*CORE_DISCONNECT_TOLERANCE;
|
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());
|
sleeptime = qMin(sleeptime, CoreFile::corefileIterationInterval());
|
||||||
toxTimer->start(sleeptime);
|
toxTimer->start(sleeptime);
|
||||||
}
|
}
|
||||||
|
@ -1196,7 +1194,7 @@ QString Core::getPeerName(const ToxId& id) const
|
||||||
|
|
||||||
bool Core::isReady()
|
bool Core::isReady()
|
||||||
{
|
{
|
||||||
return toxav && tox && ready;
|
return av && av->getToxAv() && tox && ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::setNospam(uint32_t nospam)
|
void Core::setNospam(uint32_t nospam)
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Core : public QObject
|
||||||
public:
|
public:
|
||||||
explicit Core(QThread* coreThread, Profile& profile);
|
explicit Core(QThread* coreThread, Profile& profile);
|
||||||
static Core* getInstance(); ///< Returns the global widget's Core instance
|
static Core* getInstance(); ///< Returns the global widget's Core instance
|
||||||
const CoreAV* getAv() const;
|
CoreAV* getAv();
|
||||||
~Core();
|
~Core();
|
||||||
|
|
||||||
static const QString TOX_EXT;
|
static const QString TOX_EXT;
|
||||||
|
@ -192,21 +192,6 @@ signals:
|
||||||
|
|
||||||
void fileSendFailed(uint32_t friendId, const QString& fname);
|
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:
|
private:
|
||||||
static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage,
|
static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage,
|
||||||
size_t cMessageSize, void* core);
|
size_t cMessageSize, void* core);
|
||||||
|
@ -245,7 +230,6 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tox* tox;
|
Tox* tox;
|
||||||
ToxAV* toxav;
|
|
||||||
CoreAV* av;
|
CoreAV* av;
|
||||||
QTimer *toxTimer;
|
QTimer *toxTimer;
|
||||||
Profile& profile;
|
Profile& profile;
|
||||||
|
|
|
@ -32,132 +32,140 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
QVector<ToxCall> CoreAV::calls;
|
QHash<uint32_t, ToxCall> CoreAV::calls;
|
||||||
QHash<int, ToxGroupCall> CoreAV::groupCalls;
|
QHash<int, ToxGroupCall> CoreAV::groupCalls;
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
|
||||||
QVector<AudioFilterer*> 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<TOXAV_FRIEND_CALL_STATE>(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();
|
Audio::getInstance().subscribeInput();
|
||||||
|
sendAudioTimer->setInterval(5);
|
||||||
|
sendAudioTimer->setSingleShot(true);
|
||||||
|
QObject::connect(sendAudioTimer, &QTimer::timeout, [=,&av](){av.sendCallAudio(friendNum);});
|
||||||
|
sendAudioTimer->start();
|
||||||
|
|
||||||
// Go
|
if (videoEnabled)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
calls[callId].videoSource = new CoreVideoSource;
|
videoSource = new CoreVideoSource;
|
||||||
CameraSource& source = CameraSource::getInstance();
|
CameraSource& source = CameraSource::getInstance();
|
||||||
source.subscribe();
|
source.subscribe();
|
||||||
connect(&source, &VideoSource::frameAvailable,
|
QObject::connect(&source, &VideoSource::frameAvailable,
|
||||||
[=](std::shared_ptr<VideoFrame> frame){sendCallVideo(callId,toxav,frame);});
|
[=,&av](std::shared_ptr<VideoFrame> frame){av.sendCallVideo(friendNum,frame);});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
if (Settings::getInstance().getFilterAudio())
|
if (Settings::getInstance().getFilterAudio())
|
||||||
{
|
{
|
||||||
filterer[callId] = new AudioFilterer();
|
filterer = new AudioFilterer();
|
||||||
filterer[callId]->startFilter(48000);
|
filterer->startFilter(48000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete filterer[callId];
|
filterer = nullptr;
|
||||||
filterer[callId] = nullptr;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::answerCall(int32_t callId)
|
ToxCall::~ToxCall()
|
||||||
{
|
{
|
||||||
|
QObject::disconnect(sendAudioTimer, nullptr, nullptr, nullptr);
|
||||||
}
|
sendAudioTimer->stop();
|
||||||
|
if (videoEnabled)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
CameraSource::getInstance().unsubscribe();
|
CameraSource::getInstance().unsubscribe();
|
||||||
if (calls[callId].videoSource)
|
if (videoSource)
|
||||||
{
|
{
|
||||||
calls[callId].videoSource->setDeleteOnClose(true);
|
videoSource->setDeleteOnClose(true);
|
||||||
calls[callId].videoSource = nullptr;
|
videoSource = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio::getInstance().unsubscribeInput();
|
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"<<err;
|
||||||
|
calls.remove(friendNum);
|
||||||
|
emit avCallFailed(friendNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::startCall(uint32_t friendId, bool video)
|
||||||
|
{
|
||||||
|
qWarning() << "START CALL CALLED";
|
||||||
|
assert(!calls.contains(friendId));
|
||||||
|
uint32_t videoBitrate = video ? VIDEO_DEFAULT_BITRATE : 0;
|
||||||
|
if (!toxav_call(toxav, friendId, AUDIO_DEFAULT_BITRATE, videoBitrate, nullptr))
|
||||||
|
{
|
||||||
|
emit avCallFailed(friendId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
calls.insert(friendId, {friendId, video, *this});
|
||||||
|
emit avRinging(friendId, video);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::cancelCall(uint32_t friendId)
|
||||||
|
{
|
||||||
|
qDebug() << QString("Cancelling call with %1").arg(friendId);
|
||||||
|
toxav_call_control(toxav, friendId, TOXAV_CALL_CONTROL_CANCEL, nullptr);
|
||||||
|
calls.remove(friendId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint16_t samples, void *user_data)
|
void CoreAV::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint16_t samples, void *user_data)
|
||||||
{
|
{
|
||||||
Q_UNUSED(user_data);
|
Q_UNUSED(user_data);
|
||||||
|
|
||||||
if (!calls[callId].active || calls[callId].muteVol)
|
if (!calls.contains(callId) || calls[callId].muteVol)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!calls[callId].alSource)
|
if (!calls[callId].alSource)
|
||||||
|
@ -168,9 +176,9 @@ void CoreAV::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uin
|
||||||
// playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate);
|
// playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::sendCallAudio(int32_t callId, ToxAV* toxav)
|
void CoreAV::sendCallAudio(uint32_t callId)
|
||||||
{
|
{
|
||||||
if (!calls[callId].active)
|
if (!calls.contains(callId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (calls[callId].muteMic || !Audio::getInstance().isInputReady())
|
if (calls[callId].muteMic || !Audio::getInstance().isInputReady())
|
||||||
|
@ -226,15 +234,16 @@ void CoreAV::playCallVideo(void*, int32_t callId, const vpx_image *img, void *us
|
||||||
{
|
{
|
||||||
Q_UNUSED(user_data);
|
Q_UNUSED(user_data);
|
||||||
|
|
||||||
if (!calls[callId].active || !calls[callId].videoEnabled)
|
if (!calls.contains(callId) || !calls[callId].videoEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
calls[callId].videoSource->pushFrame(img);
|
calls[callId].videoSource->pushFrame(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::sendCallVideo(int32_t callId, ToxAV* toxav, std::shared_ptr<VideoFrame> vframe)
|
void CoreAV::sendCallVideo(uint32_t callId, std::shared_ptr<VideoFrame> 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;
|
return;
|
||||||
|
|
||||||
// This frame shares vframe's buffers, we don't call vpx_img_free but just delete it
|
// 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_ptr<VideoFr
|
||||||
delete frame;
|
delete frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::micMuteToggle(int32_t callId)
|
void CoreAV::micMuteToggle(uint32_t callId)
|
||||||
{
|
{
|
||||||
if (calls[callId].active)
|
if (calls.contains(callId))
|
||||||
calls[callId].muteMic = !calls[callId].muteMic;
|
calls[callId].muteMic = !calls[callId].muteMic;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::volMuteToggle(int32_t callId)
|
void CoreAV::volMuteToggle(uint32_t callId)
|
||||||
{
|
{
|
||||||
if (calls[callId].active)
|
if (calls.contains(callId))
|
||||||
calls[callId].muteVol = !calls[callId].muteVol;
|
calls[callId].muteVol = !calls[callId].muteVol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,9 +329,10 @@ void CoreAV::playAudioBuffer(ALuint alSource, const int16_t *data, int samples,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoSource *CoreAV::getVideoSourceFromCall(int callNumber)
|
VideoSource *CoreAV::getVideoSourceFromCall(int friendNum)
|
||||||
{
|
{
|
||||||
return calls[callNumber].videoSource;
|
assert(calls.contains(friendNum));
|
||||||
|
return calls[friendNum].videoSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::joinGroupCall(int groupId)
|
void CoreAV::joinGroupCall(int groupId)
|
||||||
|
@ -338,9 +348,6 @@ void CoreAV::joinGroupCall(int groupId)
|
||||||
Audio::getInstance().subscribeInput();
|
Audio::getInstance().subscribeInput();
|
||||||
|
|
||||||
// Go
|
// Go
|
||||||
Core* core = Core::getInstance();
|
|
||||||
ToxAV* toxav = core->toxav;
|
|
||||||
|
|
||||||
groupCalls[groupId].sendAudioTimer = new QTimer();
|
groupCalls[groupId].sendAudioTimer = new QTimer();
|
||||||
groupCalls[groupId].active = true;
|
groupCalls[groupId].active = true;
|
||||||
groupCalls[groupId].sendAudioTimer->setInterval(5);
|
groupCalls[groupId].sendAudioTimer->setInterval(5);
|
||||||
|
@ -412,17 +419,17 @@ void CoreAV::enableGroupCallVol(int groupId)
|
||||||
groupCalls[groupId].muteVol = false;
|
groupCalls[groupId].muteVol = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoreAV::isGroupCallMicEnabled(int groupId)
|
bool CoreAV::isGroupCallMicEnabled(int groupId) const
|
||||||
{
|
{
|
||||||
return !groupCalls[groupId].muteMic;
|
return !groupCalls[groupId].muteMic;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoreAV::isGroupCallVolEnabled(int groupId)
|
bool CoreAV::isGroupCallVolEnabled(int groupId) const
|
||||||
{
|
{
|
||||||
return !groupCalls[groupId].muteVol;
|
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;
|
return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV;
|
||||||
}
|
}
|
||||||
|
@ -438,7 +445,7 @@ void CoreAV::resetCallSources()
|
||||||
|
|
||||||
for (ToxCall& call : calls)
|
for (ToxCall& call : calls)
|
||||||
{
|
{
|
||||||
if (call.active && call.alSource)
|
if (call.alSource)
|
||||||
{
|
{
|
||||||
ALuint tmp = call.alSource;
|
ALuint tmp = call.alSource;
|
||||||
call.alSource = 0;
|
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<CoreAV*>(_self);
|
||||||
|
calls.insert(friendNum, {friendNum, video, *self});
|
||||||
|
emit reinterpret_cast<CoreAV*>(self)->avInvite(friendNum, video);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::stateCallback(ToxAV *toxAV, uint32_t friendNum, uint32_t state, void *_self)
|
||||||
|
{
|
||||||
|
qWarning() << "STATE IS "<<state;
|
||||||
|
CoreAV* self = static_cast<CoreAV*>(_self);
|
||||||
|
|
||||||
|
assert(self->calls.contains(friendNum));
|
||||||
|
ToxCall& call = self->calls[friendNum];
|
||||||
|
|
||||||
|
if (state & TOXAV_FRIEND_CALL_STATE_ERROR)
|
||||||
|
{
|
||||||
|
qWarning() << "Call with friend"<<friendNum<<"died of unnatural causes";
|
||||||
|
calls.remove(friendNum);
|
||||||
|
emit self->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<TOXAV_FRIEND_CALL_STATE>(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::audioBitrateCallback(ToxAV *toxAV, uint32_t friendNum, bool stable, uint32_t rate, void *self)
|
||||||
|
{
|
||||||
|
qWarning() << "AUDIO BITRATE IS "<<rate<<" STABILITY:"<<stable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::videoBitrateCallback(ToxAV *toxAV, uint32_t friendNum, bool stable, uint32_t rate, void *self)
|
||||||
|
{
|
||||||
|
qWarning() << "AUDIO BITRATE IS "<<rate<<" STABILITY:"<<stable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::audioFrameCallback(ToxAV *toxAV, uint32_t friendNum, const int16_t *pcm, size_t sampleCount, uint8_t channels, uint32_t samplingRate, void *self)
|
||||||
|
{
|
||||||
|
qWarning() << "AUDIO FRAME";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreAV::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)
|
||||||
|
{
|
||||||
|
qWarning() << "VIDEO FRAME";
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
#include <tox/toxav.h>
|
#include <tox/toxav.h>
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
|
@ -43,19 +44,26 @@ class CoreVideoSource;
|
||||||
class CameraSource;
|
class CameraSource;
|
||||||
class VideoSource;
|
class VideoSource;
|
||||||
class VideoFrame;
|
class VideoFrame;
|
||||||
|
class CoreAV;
|
||||||
struct vpx_image;
|
struct vpx_image;
|
||||||
|
|
||||||
struct ToxCall
|
struct ToxCall
|
||||||
{
|
{
|
||||||
|
ToxCall() = default;
|
||||||
|
ToxCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av);
|
||||||
|
~ToxCall();
|
||||||
|
|
||||||
QTimer *sendAudioTimer;
|
QTimer *sendAudioTimer;
|
||||||
int32_t callId;
|
uint32_t friendNum;
|
||||||
uint32_t friendId;
|
|
||||||
bool videoEnabled;
|
|
||||||
bool active;
|
|
||||||
bool muteMic;
|
bool muteMic;
|
||||||
bool muteVol;
|
bool muteVol;
|
||||||
|
bool videoEnabled; ///< True if our user asked for a video call, sending and recving
|
||||||
ALuint alSource;
|
ALuint alSource;
|
||||||
CoreVideoSource* videoSource;
|
CoreVideoSource* videoSource;
|
||||||
|
TOXAV_FRIEND_CALL_STATE state; ///< State of the peer (not ours!)
|
||||||
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
|
AudioFilterer* filterer;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ToxGroupCall
|
struct ToxGroupCall
|
||||||
|
@ -73,49 +81,79 @@ class CoreAV : public QThread
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CoreAV() = default;
|
CoreAV(Tox* tox);
|
||||||
~CoreAV();
|
~CoreAV();
|
||||||
|
|
||||||
static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
|
const ToxAV* getToxAv() const;
|
||||||
static void prepareCall(uint32_t friendId, int callId, ToxAV *toxav, bool videoEnabled);
|
|
||||||
static void cleanupCall(int callId);
|
void process();
|
||||||
static void playCallAudio(void *toxav, int32_t callId, const int16_t *data,
|
|
||||||
|
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
|
uint16_t samples, void *user_data); // Callback
|
||||||
static void sendCallAudio(int callId, ToxAV* toxav);
|
void sendCallAudio(uint32_t friendId);
|
||||||
static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples,
|
void playAudioBuffer(ALuint alSource, const int16_t *data, int samples,
|
||||||
unsigned channels, int sampleRate);
|
unsigned channels, int sampleRate);
|
||||||
static void playCallVideo(void *toxav, int32_t callId, const vpx_image* img, void *user_data);
|
void playCallVideo(void *toxav, int32_t callId, const vpx_image* img, void *user_data);
|
||||||
static void sendCallVideo(int callId, ToxAV* toxav, std::shared_ptr<VideoFrame> frame);
|
void sendCallVideo(uint32_t friendId, std::shared_ptr<VideoFrame> frame);
|
||||||
static void sendGroupCallAudio(int groupId, ToxAV* toxav);
|
void sendGroupCallAudio(int groupId, ToxAV* toxav);
|
||||||
|
|
||||||
static VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
||||||
static void resetCallSources(); ///< Forces to regenerate each call's audio sources
|
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.
|
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.
|
void leaveGroupCall(int groupId); ///< Will not leave the group, just stop the call. Call from the GUI thread.
|
||||||
static void disableGroupCallMic(int groupId);
|
void disableGroupCallMic(int groupId);
|
||||||
static void disableGroupCallVol(int groupId);
|
void disableGroupCallVol(int groupId);
|
||||||
static void enableGroupCallMic(int groupId);
|
void enableGroupCallMic(int groupId);
|
||||||
static void enableGroupCallVol(int groupId);
|
void enableGroupCallVol(int groupId);
|
||||||
static bool isGroupCallMicEnabled(int groupId);
|
bool isGroupCallMicEnabled(int groupId) const;
|
||||||
static bool isGroupCallVolEnabled(int groupId);
|
bool isGroupCallVolEnabled(int groupId) const;
|
||||||
static bool isGroupAvEnabled(int groupId); ///< True for AV groups, false for text-only groups
|
bool isGroupAvEnabled(int groupId) const; ///< True for AV groups, false for text-only groups
|
||||||
|
|
||||||
public slots:
|
void startCall(uint32_t friendId, bool video=false);
|
||||||
static void answerCall(int callId);
|
void answerCall(uint32_t friendId);
|
||||||
static void rejectCall(int callId);
|
void cancelCall(uint32_t friendId);
|
||||||
static void hangupCall(int callId);
|
|
||||||
static void startCall(uint32_t friendId, bool video=false);
|
|
||||||
static void cancelCall(int callId, uint32_t friendId);
|
|
||||||
|
|
||||||
static void micMuteToggle(int callId);
|
void micMuteToggle(uint32_t friendId);
|
||||||
static void volMuteToggle(int callId);
|
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:
|
private:
|
||||||
static QVector<ToxCall> calls;
|
static void callCallback(ToxAV *toxAV, uint32_t friendNum, bool audio, bool video, void* self);
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
static void stateCallback(ToxAV *toxAV, uint32_t friendNum, uint32_t state, void* self);
|
||||||
static QVector<AudioFilterer*> filterer;
|
static void audioBitrateCallback(ToxAV *toxAV, uint32_t friendNum, bool stable, uint32_t rate, void* self);
|
||||||
#endif
|
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<uint32_t, ToxCall> calls;
|
||||||
static QHash<int, ToxGroupCall> groupCalls; // Maps group IDs to ToxGroupCalls
|
static QHash<int, ToxGroupCall> groupCalls; // Maps group IDs to ToxGroupCalls
|
||||||
|
|
||||||
friend class Audio;
|
friend class Audio;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "nexus.h"
|
#include "nexus.h"
|
||||||
#include "src/persistence/profile.h"
|
#include "src/persistence/profile.h"
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
|
#include "src/core/coreav.h"
|
||||||
#include "persistence/settings.h"
|
#include "persistence/settings.h"
|
||||||
#include "video/camerasource.h"
|
#include "video/camerasource.h"
|
||||||
#include "widget/gui.h"
|
#include "widget/gui.h"
|
||||||
|
@ -189,6 +190,7 @@ void Nexus::showMainGUI()
|
||||||
|
|
||||||
// Connections
|
// Connections
|
||||||
Core* core = profile->getCore();
|
Core* core = profile->getCore();
|
||||||
|
CoreAV* coreav = core->getAv();
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected);
|
connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected);
|
||||||
connect(core, &Core::disconnected, androidgui, &AndroidGUI::onDisconnected);
|
connect(core, &Core::disconnected, androidgui, &AndroidGUI::onDisconnected);
|
||||||
|
@ -227,7 +229,7 @@ void Nexus::showMainGUI()
|
||||||
connect(core, &Core::groupTitleChanged, widget, &Widget::onGroupTitleChanged);
|
connect(core, &Core::groupTitleChanged, widget, &Widget::onGroupTitleChanged);
|
||||||
connect(core, &Core::groupPeerAudioPlaying, widget, &Widget::onGroupPeerAudioPlaying);
|
connect(core, &Core::groupPeerAudioPlaying, widget, &Widget::onGroupPeerAudioPlaying);
|
||||||
connect(core, &Core::emptyGroupCreated, widget, &Widget::onEmptyGroupCreated);
|
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::friendTypingChanged, widget, &Widget::onFriendTypingChanged);
|
||||||
|
|
||||||
connect(core, &Core::messageSentResult, widget, &Widget::onMessageSendResult);
|
connect(core, &Core::messageSentResult, widget, &Widget::onMessageSendResult);
|
||||||
|
|
|
@ -50,6 +50,7 @@ private:
|
||||||
std::atomic_bool biglock; ///< Fast lock
|
std::atomic_bool biglock; ///< Fast lock
|
||||||
|
|
||||||
friend class CoreAV;
|
friend class CoreAV;
|
||||||
|
friend struct ToxCall;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COREVIDEOSOURCE_H
|
#endif // COREVIDEOSOURCE_H
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
|
|
||||||
ChatForm::ChatForm(Friend* chatFriend)
|
ChatForm::ChatForm(Friend* chatFriend)
|
||||||
: f(chatFriend)
|
: f(chatFriend)
|
||||||
, callId{0}, isTyping{false}
|
, isTyping{false}
|
||||||
{
|
{
|
||||||
nameLabel->setText(f->getDisplayedName());
|
nameLabel->setText(f->getDisplayedName());
|
||||||
|
|
||||||
|
@ -251,14 +251,13 @@ void ChatForm::onFileRecvRequest(ToxFile file)
|
||||||
Widget::getInstance()->updateFriendActivity(f);
|
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())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvInvite, callId: " << CallId;
|
qDebug() << "onAvInvite";
|
||||||
|
|
||||||
callId = CallId;
|
|
||||||
callButton->disconnect();
|
callButton->disconnect();
|
||||||
videoButton->disconnect();
|
videoButton->disconnect();
|
||||||
if (video)
|
if (video)
|
||||||
|
@ -302,16 +301,15 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video)
|
||||||
Widget::getInstance()->newFriendMessageAlert(FriendId);
|
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())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvStart, callId: " << CallId;
|
qDebug() << "onAvStart";
|
||||||
|
|
||||||
audioInputFlag = true;
|
audioInputFlag = true;
|
||||||
audioOutputFlag = true;
|
audioOutputFlag = true;
|
||||||
callId = CallId;
|
|
||||||
callButton->disconnect();
|
callButton->disconnect();
|
||||||
videoButton->disconnect();
|
videoButton->disconnect();
|
||||||
|
|
||||||
|
@ -354,12 +352,12 @@ void ChatForm::onAvStart(uint32_t FriendId, int CallId, bool video)
|
||||||
startCounter();
|
startCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvCancel(uint32_t FriendId, int CallId)
|
void ChatForm::onAvCancel(uint32_t FriendId)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvCancel, callId: " << CallId;
|
qDebug() << "onAvCancel";
|
||||||
|
|
||||||
delete callConfirm;
|
delete callConfirm;
|
||||||
callConfirm = nullptr;
|
callConfirm = nullptr;
|
||||||
|
@ -374,14 +372,13 @@ void ChatForm::onAvCancel(uint32_t FriendId, int CallId)
|
||||||
QDateTime::currentDateTime());
|
QDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video)
|
void ChatForm::onAvRinging(uint32_t FriendId, bool video)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvRinging, callId: " << CallId;
|
qDebug() << "onAvRinging";
|
||||||
|
|
||||||
callId = CallId;
|
|
||||||
callButton->disconnect();
|
callButton->disconnect();
|
||||||
videoButton->disconnect();
|
videoButton->disconnect();
|
||||||
if (video)
|
if (video)
|
||||||
|
@ -414,14 +411,12 @@ void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video)
|
||||||
Widget::getInstance()->updateFriendActivity(f);
|
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())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvStarting, callId:" << CallId;
|
qDebug() << "onAvStarting";
|
||||||
|
|
||||||
callId = CallId;
|
|
||||||
|
|
||||||
callButton->disconnect();
|
callButton->disconnect();
|
||||||
videoButton->disconnect();
|
videoButton->disconnect();
|
||||||
|
@ -451,12 +446,12 @@ void ChatForm::onAvStarting(uint32_t FriendId, int CallId, bool video)
|
||||||
startCounter();
|
startCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvEnding(uint32_t FriendId, int CallId)
|
void ChatForm::onAvEnding(uint32_t FriendId)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvEnding, callId: " << CallId;
|
qDebug() << "onAvEnding";
|
||||||
|
|
||||||
delete callConfirm;
|
delete callConfirm;
|
||||||
callConfirm = nullptr;
|
callConfirm = nullptr;
|
||||||
|
@ -467,12 +462,12 @@ void ChatForm::onAvEnding(uint32_t FriendId, int CallId)
|
||||||
hideNetcam();
|
hideNetcam();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvEnd(uint32_t FriendId, int CallId)
|
void ChatForm::onAvEnd(uint32_t FriendId)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvEnd, callId: " << CallId;
|
qDebug() << "onAvEnd";
|
||||||
|
|
||||||
delete callConfirm;
|
delete callConfirm;
|
||||||
callConfirm = nullptr;
|
callConfirm = nullptr;
|
||||||
|
@ -482,12 +477,12 @@ void ChatForm::onAvEnd(uint32_t FriendId, int CallId)
|
||||||
hideNetcam();
|
hideNetcam();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvRequestTimeout(uint32_t FriendId, int CallId)
|
void ChatForm::onAvRequestTimeout(uint32_t FriendId)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvRequestTimeout, callId: " << CallId;
|
qDebug() << "onAvRequestTimeout";
|
||||||
|
|
||||||
delete callConfirm;
|
delete callConfirm;
|
||||||
callConfirm = nullptr;
|
callConfirm = nullptr;
|
||||||
|
@ -498,7 +493,7 @@ void ChatForm::onAvRequestTimeout(uint32_t FriendId, int CallId)
|
||||||
hideNetcam();
|
hideNetcam();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvPeerTimeout(uint32_t FriendId, int)
|
void ChatForm::onAvPeerTimeout(uint32_t FriendId)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
@ -514,7 +509,7 @@ void ChatForm::onAvPeerTimeout(uint32_t FriendId, int)
|
||||||
hideNetcam();
|
hideNetcam();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onAvRejected(uint32_t FriendId, int)
|
void ChatForm::onAvRejected(uint32_t FriendId)
|
||||||
{
|
{
|
||||||
if (FriendId != f->getFriendID())
|
if (FriendId != f->getFriendID())
|
||||||
return;
|
return;
|
||||||
|
@ -533,12 +528,12 @@ void ChatForm::onAvRejected(uint32_t FriendId, int)
|
||||||
hideNetcam();
|
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;
|
return;
|
||||||
|
|
||||||
qDebug() << "onAvMediaChange, callId: " << CallId;
|
qDebug() << "onAvMediaChange";
|
||||||
|
|
||||||
if (video)
|
if (video)
|
||||||
showNetcam();
|
showNetcam();
|
||||||
|
@ -558,7 +553,7 @@ void ChatForm::onAnswerCallTriggered()
|
||||||
|
|
||||||
audioInputFlag = true;
|
audioInputFlag = true;
|
||||||
audioOutputFlag = true;
|
audioOutputFlag = true;
|
||||||
emit answerCall(callId);
|
emit answerCall(f->getFriendID());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::onHangupCallTriggered()
|
void ChatForm::onHangupCallTriggered()
|
||||||
|
@ -571,8 +566,9 @@ void ChatForm::onHangupCallTriggered()
|
||||||
|
|
||||||
audioInputFlag = false;
|
audioInputFlag = false;
|
||||||
audioOutputFlag = false;
|
audioOutputFlag = false;
|
||||||
emit hangupCall(callId);
|
emit hangupCall(f->getFriendID());
|
||||||
|
|
||||||
|
stopCounter();
|
||||||
enableCallButtons();
|
enableCallButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,7 +584,7 @@ void ChatForm::onRejectCallTriggered()
|
||||||
|
|
||||||
audioInputFlag = false;
|
audioInputFlag = false;
|
||||||
audioOutputFlag = false;
|
audioOutputFlag = false;
|
||||||
emit rejectCall(callId);
|
emit rejectCall(f->getFriendID());
|
||||||
|
|
||||||
enableCallButtons();
|
enableCallButtons();
|
||||||
}
|
}
|
||||||
|
@ -635,7 +631,7 @@ void ChatForm::onCancelCallTriggered()
|
||||||
enableCallButtons();
|
enableCallButtons();
|
||||||
|
|
||||||
hideNetcam();
|
hideNetcam();
|
||||||
emit cancelCall(callId, f->getFriendID());
|
emit cancelCall(f->getFriendID());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatForm::enableCallButtons()
|
void ChatForm::enableCallButtons()
|
||||||
|
@ -701,7 +697,7 @@ void ChatForm::onMicMuteToggle()
|
||||||
{
|
{
|
||||||
if (audioInputFlag == true)
|
if (audioInputFlag == true)
|
||||||
{
|
{
|
||||||
emit micMuteToggle(callId);
|
emit micMuteToggle(f->getFriendID());
|
||||||
if (micButton->objectName() == "red")
|
if (micButton->objectName() == "red")
|
||||||
{
|
{
|
||||||
micButton->setObjectName("green");
|
micButton->setObjectName("green");
|
||||||
|
@ -721,7 +717,7 @@ void ChatForm::onVolMuteToggle()
|
||||||
{
|
{
|
||||||
if (audioOutputFlag == true)
|
if (audioOutputFlag == true)
|
||||||
{
|
{
|
||||||
emit volMuteToggle(callId);
|
emit volMuteToggle(f->getFriendID());
|
||||||
if (volButton->objectName() == "red")
|
if (volButton->objectName() == "red")
|
||||||
{
|
{
|
||||||
volButton->setObjectName("green");
|
volButton->setObjectName("green");
|
||||||
|
@ -757,7 +753,7 @@ GenericNetCamView *ChatForm::createNetcam()
|
||||||
{
|
{
|
||||||
qDebug() << "creating netcam";
|
qDebug() << "creating netcam";
|
||||||
NetCamView* view = new NetCamView(f->getFriendID(), this);
|
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;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,30 +52,30 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sendFile(uint32_t friendId, QString, QString, long long);
|
void sendFile(uint32_t friendId, QString, QString, long long);
|
||||||
void startCall(uint32_t FriendId, bool video);
|
void startCall(uint32_t friendId, bool video);
|
||||||
void answerCall(int callId);
|
void answerCall(uint32_t friendId);
|
||||||
void hangupCall(int callId);
|
void hangupCall(uint32_t friendId);
|
||||||
void cancelCall(int callId, uint32_t FriendId);
|
void cancelCall(uint32_t friendId);
|
||||||
void rejectCall(int callId);
|
void rejectCall(uint32_t friendId);
|
||||||
void micMuteToggle(int callId);
|
void micMuteToggle(uint32_t friendId);
|
||||||
void volMuteToggle(int callId);
|
void volMuteToggle(uint32_t friendId);
|
||||||
void aliasChanged(const QString& alias);
|
void aliasChanged(const QString& alias);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startFileSend(ToxFile file);
|
void startFileSend(ToxFile file);
|
||||||
void onFileRecvRequest(ToxFile file);
|
void onFileRecvRequest(ToxFile file);
|
||||||
void onAvInvite(uint32_t FriendId, int CallId, bool video);
|
void onAvInvite(uint32_t FriendId, bool video);
|
||||||
void onAvStart(uint32_t FriendId, int CallId, bool video);
|
void onAvStart(uint32_t FriendId, bool video);
|
||||||
void onAvCancel(uint32_t FriendId, int CallId);
|
void onAvCancel(uint32_t FriendId);
|
||||||
void onAvEnd(uint32_t FriendId, int CallId);
|
void onAvEnd(uint32_t FriendId);
|
||||||
void onAvRinging(uint32_t FriendId, int CallId, bool video);
|
void onAvRinging(uint32_t FriendId, bool video);
|
||||||
void onAvStarting(uint32_t FriendId, int CallId, bool video);
|
void onAvStarting(uint32_t FriendId, bool video);
|
||||||
void onAvEnding(uint32_t FriendId, int CallId);
|
void onAvEnding(uint32_t FriendId);
|
||||||
void onAvRequestTimeout(uint32_t FriendId, int CallId);
|
void onAvRequestTimeout(uint32_t FriendId);
|
||||||
void onAvPeerTimeout(uint32_t FriendId, int CallId);
|
void onAvPeerTimeout(uint32_t FriendId);
|
||||||
void onAvMediaChange(uint32_t FriendId, int CallId, bool video);
|
void onAvMediaChange(uint32_t FriendId, bool video);
|
||||||
void onAvCallFailed(uint32_t FriendId);
|
void onAvCallFailed(uint32_t FriendId);
|
||||||
void onAvRejected(uint32_t FriendId, int CallId);
|
void onAvRejected(uint32_t FriendId);
|
||||||
void onMicMuteToggle();
|
void onMicMuteToggle();
|
||||||
void onVolMuteToggle();
|
void onVolMuteToggle();
|
||||||
void onAvatarChange(uint32_t FriendId, const QPixmap& pic);
|
void onAvatarChange(uint32_t FriendId, const QPixmap& pic);
|
||||||
|
@ -114,7 +114,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
Friend* f;
|
Friend* f;
|
||||||
CroppingLabel *statusMessageLabel;
|
CroppingLabel *statusMessageLabel;
|
||||||
int callId;
|
|
||||||
QLabel *callDuration;
|
QLabel *callDuration;
|
||||||
QTimer *callDurationTimer;
|
QTimer *callDurationTimer;
|
||||||
QTimer typingTimer;
|
QTimer typingTimer;
|
||||||
|
|
|
@ -283,13 +283,13 @@ void GroupChatForm::onMicMuteToggle()
|
||||||
{
|
{
|
||||||
if (micButton->objectName() == "red")
|
if (micButton->objectName() == "red")
|
||||||
{
|
{
|
||||||
CoreAV::enableGroupCallMic(group->getGroupId());
|
Core::getInstance()->getAv()->enableGroupCallMic(group->getGroupId());
|
||||||
micButton->setObjectName("green");
|
micButton->setObjectName("green");
|
||||||
micButton->setToolTip(tr("Mute microphone"));
|
micButton->setToolTip(tr("Mute microphone"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CoreAV::disableGroupCallMic(group->getGroupId());
|
Core::getInstance()->getAv()->disableGroupCallMic(group->getGroupId());
|
||||||
micButton->setObjectName("red");
|
micButton->setObjectName("red");
|
||||||
micButton->setToolTip(tr("Unmute microphone"));
|
micButton->setToolTip(tr("Unmute microphone"));
|
||||||
}
|
}
|
||||||
|
@ -304,13 +304,13 @@ void GroupChatForm::onVolMuteToggle()
|
||||||
{
|
{
|
||||||
if (volButton->objectName() == "red")
|
if (volButton->objectName() == "red")
|
||||||
{
|
{
|
||||||
CoreAV::enableGroupCallVol(group->getGroupId());
|
Core::getInstance()->getAv()->enableGroupCallVol(group->getGroupId());
|
||||||
volButton->setObjectName("green");
|
volButton->setObjectName("green");
|
||||||
volButton->setToolTip(tr("Mute call"));
|
volButton->setToolTip(tr("Mute call"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CoreAV::disableGroupCallVol(group->getGroupId());
|
Core::getInstance()->getAv()->disableGroupCallVol(group->getGroupId());
|
||||||
volButton->setObjectName("red");
|
volButton->setObjectName("red");
|
||||||
volButton->setToolTip(tr("Unmute call"));
|
volButton->setToolTip(tr("Unmute call"));
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ void GroupChatForm::onCallClicked()
|
||||||
{
|
{
|
||||||
if (!inCall)
|
if (!inCall)
|
||||||
{
|
{
|
||||||
CoreAV::joinGroupCall(group->getGroupId());
|
Core::getInstance()->getAv()->joinGroupCall(group->getGroupId());
|
||||||
audioInputFlag = true;
|
audioInputFlag = true;
|
||||||
audioOutputFlag = true;
|
audioOutputFlag = true;
|
||||||
callButton->setObjectName("red");
|
callButton->setObjectName("red");
|
||||||
|
@ -340,7 +340,7 @@ void GroupChatForm::onCallClicked()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CoreAV::leaveGroupCall(group->getGroupId());
|
Core::getInstance()->getAv()->leaveGroupCall(group->getGroupId());
|
||||||
audioInputFlag = false;
|
audioInputFlag = false;
|
||||||
audioOutputFlag = false;
|
audioOutputFlag = false;
|
||||||
callButton->setObjectName("green");
|
callButton->setObjectName("green");
|
||||||
|
@ -376,9 +376,9 @@ void GroupChatForm::keyPressEvent(QKeyEvent* ev)
|
||||||
// Push to talk (CTRL+P)
|
// Push to talk (CTRL+P)
|
||||||
if (ev->key() == Qt::Key_P && (ev->modifiers() & Qt::ControlModifier) && inCall)
|
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->setObjectName("green");
|
||||||
micButton->style()->polish(micButton);
|
micButton->style()->polish(micButton);
|
||||||
Style::repolish(micButton);
|
Style::repolish(micButton);
|
||||||
|
@ -394,9 +394,9 @@ void GroupChatForm::keyReleaseEvent(QKeyEvent* ev)
|
||||||
// Push to talk (CTRL+P)
|
// Push to talk (CTRL+P)
|
||||||
if (ev->key() == Qt::Key_P && (ev->modifiers() & Qt::ControlModifier) && inCall)
|
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->setObjectName("red");
|
||||||
micButton->style()->polish(micButton);
|
micButton->style()->polish(micButton);
|
||||||
Style::repolish(micButton);
|
Style::repolish(micButton);
|
||||||
|
|
|
@ -359,7 +359,7 @@ void GeneralForm::onUseProxyUpdated()
|
||||||
|
|
||||||
void GeneralForm::onReconnectClicked()
|
void GeneralForm::onReconnectClicked()
|
||||||
{
|
{
|
||||||
if (CoreAV::anyActiveCalls())
|
if (Core::getInstance()->getAv()->anyActiveCalls())
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this, tr("Call active", "popup title"),
|
QMessageBox::warning(this, tr("Call active", "popup title"),
|
||||||
tr("You can't disconnect while a call is active!", "popup text"));
|
tr("You can't disconnect while a call is active!", "popup text"));
|
||||||
|
|
|
@ -882,6 +882,7 @@ void Widget::addFriend(int friendId, const QString &userId)
|
||||||
contactListWidget->addFriendWidget(newfriend->getFriendWidget(),Status::Offline,Settings::getInstance().getFriendCircleID(newfriend->getToxId()));
|
contactListWidget->addFriendWidget(newfriend->getFriendWidget(),Status::Offline,Settings::getInstance().getFriendCircleID(newfriend->getToxId()));
|
||||||
|
|
||||||
Core* core = Nexus::getCore();
|
Core* core = Nexus::getCore();
|
||||||
|
CoreAV* coreav = core->getAv();
|
||||||
connect(newfriend, &Friend::displayedNameChanged, this, &Widget::onFriendDisplayChanged);
|
connect(newfriend, &Friend::displayedNameChanged, this, &Widget::onFriendDisplayChanged);
|
||||||
connect(settingsWidget, &SettingsWidget::compactToggled, newfriend->getFriendWidget(), &GenericChatroomWidget::compactChange);
|
connect(settingsWidget, &SettingsWidget::compactToggled, newfriend->getFriendWidget(), &GenericChatroomWidget::compactChange);
|
||||||
connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*,bool)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*,bool)));
|
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(), &GenericChatForm::sendAction, core, &Core::sendAction);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::sendFile, core, &Core::sendFile);
|
connect(newfriend->getChatForm(), &ChatForm::sendFile, core, &Core::sendFile);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::answerCall, core->getAv(), &CoreAV::answerCall);
|
connect(newfriend->getChatForm(), &ChatForm::answerCall, core->getAv(), &CoreAV::answerCall);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::hangupCall, core->getAv(), &CoreAV::hangupCall);
|
connect(newfriend->getChatForm(), &ChatForm::hangupCall, core->getAv(), &CoreAV::cancelCall);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::rejectCall, core->getAv(), &CoreAV::rejectCall);
|
connect(newfriend->getChatForm(), &ChatForm::rejectCall, core->getAv(), &CoreAV::cancelCall);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::startCall, core->getAv(), &CoreAV::startCall);
|
connect(newfriend->getChatForm(), &ChatForm::startCall, core->getAv(), &CoreAV::startCall);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::cancelCall, core->getAv(), &CoreAV::cancelCall);
|
connect(newfriend->getChatForm(), &ChatForm::cancelCall, core->getAv(), &CoreAV::cancelCall);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::micMuteToggle, core->getAv(), &CoreAV::micMuteToggle);
|
connect(newfriend->getChatForm(), &ChatForm::micMuteToggle, core->getAv(), &CoreAV::micMuteToggle);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::volMuteToggle, core->getAv(), &CoreAV::volMuteToggle);
|
connect(newfriend->getChatForm(), &ChatForm::volMuteToggle, core->getAv(), &CoreAV::volMuteToggle);
|
||||||
connect(newfriend->getChatForm(), &ChatForm::aliasChanged, newfriend->getFriendWidget(), &FriendWidget::setAlias);
|
connect(newfriend->getChatForm(), &ChatForm::aliasChanged, newfriend->getFriendWidget(), &FriendWidget::setAlias);
|
||||||
connect(core, &Core::fileReceiveRequested, newfriend->getChatForm(), &ChatForm::onFileRecvRequest);
|
connect(core, &Core::fileReceiveRequested, newfriend->getChatForm(), &ChatForm::onFileRecvRequest);
|
||||||
connect(core, &Core::avInvite, newfriend->getChatForm(), &ChatForm::onAvInvite);
|
connect(coreav, &CoreAV::avInvite, newfriend->getChatForm(), &ChatForm::onAvInvite);
|
||||||
connect(core, &Core::avStart, newfriend->getChatForm(), &ChatForm::onAvStart);
|
connect(coreav, &CoreAV::avStart, newfriend->getChatForm(), &ChatForm::onAvStart);
|
||||||
connect(core, &Core::avCancel, newfriend->getChatForm(), &ChatForm::onAvCancel);
|
connect(coreav, &CoreAV::avCancel, newfriend->getChatForm(), &ChatForm::onAvCancel);
|
||||||
connect(core, &Core::avEnd, newfriend->getChatForm(), &ChatForm::onAvEnd);
|
connect(coreav, &CoreAV::avEnd, newfriend->getChatForm(), &ChatForm::onAvEnd);
|
||||||
connect(core, &Core::avRinging, newfriend->getChatForm(), &ChatForm::onAvRinging);
|
connect(coreav, &CoreAV::avRinging, newfriend->getChatForm(), &ChatForm::onAvRinging);
|
||||||
connect(core, &Core::avStarting, newfriend->getChatForm(), &ChatForm::onAvStarting);
|
connect(coreav, &CoreAV::avStarting, newfriend->getChatForm(), &ChatForm::onAvStarting);
|
||||||
connect(core, &Core::avEnding, newfriend->getChatForm(), &ChatForm::onAvEnding);
|
connect(coreav, &CoreAV::avEnding, newfriend->getChatForm(), &ChatForm::onAvEnding);
|
||||||
connect(core, &Core::avRequestTimeout, newfriend->getChatForm(), &ChatForm::onAvRequestTimeout);
|
connect(coreav, &CoreAV::avRequestTimeout, newfriend->getChatForm(), &ChatForm::onAvRequestTimeout);
|
||||||
connect(core, &Core::avPeerTimeout, newfriend->getChatForm(), &ChatForm::onAvPeerTimeout);
|
connect(coreav, &CoreAV::avPeerTimeout, newfriend->getChatForm(), &ChatForm::onAvPeerTimeout);
|
||||||
connect(core, &Core::avMediaChange, newfriend->getChatForm(), &ChatForm::onAvMediaChange);
|
connect(coreav, &CoreAV::avMediaChange, newfriend->getChatForm(), &ChatForm::onAvMediaChange);
|
||||||
connect(core, &Core::avCallFailed, newfriend->getChatForm(), &ChatForm::onAvCallFailed);
|
connect(coreav, &CoreAV::avCallFailed, newfriend->getChatForm(), &ChatForm::onAvCallFailed);
|
||||||
connect(core, &Core::avRejected, newfriend->getChatForm(), &ChatForm::onAvRejected);
|
connect(coreav, &CoreAV::avRejected, newfriend->getChatForm(), &ChatForm::onAvRejected);
|
||||||
connect(core, &Core::friendAvatarChanged, newfriend->getChatForm(), &ChatForm::onAvatarChange);
|
connect(core, &Core::friendAvatarChanged, newfriend->getChatForm(), &ChatForm::onAvatarChange);
|
||||||
connect(core, &Core::friendAvatarChanged, newfriend->getFriendWidget(), &FriendWidget::onAvatarChange);
|
connect(core, &Core::friendAvatarChanged, newfriend->getFriendWidget(), &FriendWidget::onAvatarChange);
|
||||||
connect(core, &Core::friendAvatarRemoved, newfriend->getChatForm(), &ChatForm::onAvatarRemoved);
|
connect(core, &Core::friendAvatarRemoved, newfriend->getChatForm(), &ChatForm::onAvatarRemoved);
|
||||||
|
@ -1589,7 +1590,7 @@ Group *Widget::createGroup(int groupId)
|
||||||
Core* core = Nexus::getCore();
|
Core* core = Nexus::getCore();
|
||||||
|
|
||||||
QString groupName = QString("Groupchat #%1").arg(groupId);
|
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());
|
contactListWidget->addGroupWidget(newgroup->getGroupWidget());
|
||||||
newgroup->getGroupWidget()->updateStatusLight();
|
newgroup->getGroupWidget()->updateStatusLight();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user