mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
refactor(call): Refactor toxcall and disconnect lambda on destruction
Fixes #3840 Move audio and video state into ToxCall which both ToxFriendCall and ToxGroupCall inherit from
This commit is contained in:
parent
96ae4284a0
commit
9216549d6e
|
@ -204,7 +204,11 @@ bool CoreAV::isCallStarted(const Group* g) const
|
||||||
*/
|
*/
|
||||||
bool CoreAV::isCallActive(const Friend* f) const
|
bool CoreAV::isCallActive(const Friend* f) const
|
||||||
{
|
{
|
||||||
return isCallStarted(f) && calls[f->getId()].isActive();
|
auto it = calls.find(f->getId());
|
||||||
|
if (it == calls.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return isCallStarted(f) && it->second.isActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,12 +218,17 @@ bool CoreAV::isCallActive(const Friend* f) const
|
||||||
*/
|
*/
|
||||||
bool CoreAV::isCallActive(const Group* g) const
|
bool CoreAV::isCallActive(const Group* g) const
|
||||||
{
|
{
|
||||||
return isCallStarted(g) && groupCalls[g->getId()].isActive();
|
auto it = groupCalls.find(g->getId());
|
||||||
|
if (it == groupCalls.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return isCallStarted(g) && it->second.isActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoreAV::isCallVideoEnabled(const Friend* f) const
|
bool CoreAV::isCallVideoEnabled(const Friend* f) const
|
||||||
{
|
{
|
||||||
return isCallStarted(f) && calls[f->getId()].getVideoEnabled();
|
auto it = calls.find(f->getId());
|
||||||
|
return isCallStarted(f) && it->second.getVideoEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoreAV::answerCall(uint32_t friendNum, bool video)
|
bool CoreAV::answerCall(uint32_t friendNum, bool video)
|
||||||
|
@ -240,17 +249,18 @@ bool CoreAV::answerCall(uint32_t friendNum, bool video)
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << QString("answering call %1").arg(friendNum);
|
qDebug() << QString("answering call %1").arg(friendNum);
|
||||||
assert(calls.find(friendNum) != calls.end());
|
auto it = calls.find(friendNum);
|
||||||
|
assert(it != calls.end());
|
||||||
TOXAV_ERR_ANSWER err;
|
TOXAV_ERR_ANSWER err;
|
||||||
|
|
||||||
const uint32_t videoBitrate = video ? VIDEO_DEFAULT_BITRATE : 0;
|
const uint32_t videoBitrate = video ? VIDEO_DEFAULT_BITRATE : 0;
|
||||||
if (toxav_answer(toxav, friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, &err)) {
|
if (toxav_answer(toxav, friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, &err)) {
|
||||||
calls[friendNum].setActive(true);
|
it->second.setActive(true);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Failed to answer call with error" << err;
|
qWarning() << "Failed to answer call with error" << err;
|
||||||
toxav_call_control(toxav, friendNum, TOXAV_CALL_CONTROL_CANCEL, nullptr);
|
toxav_call_control(toxav, friendNum, TOXAV_CALL_CONTROL_CANCEL, nullptr);
|
||||||
calls.erase(friendNum);
|
calls.erase(it);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,7 +283,8 @@ bool CoreAV::startCall(uint32_t friendNum, bool video)
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << QString("Starting call with %1").arg(friendNum);
|
qDebug() << QString("Starting call with %1").arg(friendNum);
|
||||||
if (calls.find(friendNum) != calls.end()) {
|
auto it = calls.find(friendNum);
|
||||||
|
if (it != calls.end()) {
|
||||||
qWarning() << QString("Can't start call with %1, we're already in this call!").arg(friendNum);
|
qWarning() << QString("Can't start call with %1, we're already in this call!").arg(friendNum);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -282,8 +293,8 @@ bool CoreAV::startCall(uint32_t friendNum, bool video)
|
||||||
if (!toxav_call(toxav, friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, nullptr))
|
if (!toxav_call(toxav, friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
calls.insert(std::make_pair(friendNum, ToxFriendCall(friendNum, video, *this)));
|
auto ret = calls.insert(std::make_pair(friendNum, ToxFriendCall(friendNum, video, *this)));
|
||||||
calls[friendNum].startTimeout(friendNum);
|
ret.first->second.startTimeout(friendNum);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,13 +352,14 @@ void CoreAV::timeoutCall(uint32_t friendNum)
|
||||||
* @return False only on error, but not if there's nothing to send.
|
* @return False only on error, but not if there's nothing to send.
|
||||||
*/
|
*/
|
||||||
bool CoreAV::sendCallAudio(uint32_t callId, const int16_t* pcm, size_t samples, uint8_t chans,
|
bool CoreAV::sendCallAudio(uint32_t callId, const int16_t* pcm, size_t samples, uint8_t chans,
|
||||||
uint32_t rate)
|
uint32_t rate) const
|
||||||
{
|
{
|
||||||
if (calls.find(callId) == calls.end()) {
|
auto it = calls.find(callId);
|
||||||
|
if (it == calls.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxFriendCall& call = calls[callId];
|
ToxFriendCall const& call = it->second;
|
||||||
|
|
||||||
if (call.getMuteMic() || !call.isActive()
|
if (call.getMuteMic() || !call.isActive()
|
||||||
|| !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A)) {
|
|| !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A)) {
|
||||||
|
@ -378,11 +390,12 @@ void CoreAV::sendCallVideo(uint32_t callId, std::shared_ptr<VideoFrame> vframe)
|
||||||
{
|
{
|
||||||
// We might be running in the FFmpeg thread and holding the CameraSource lock
|
// We might be running in the FFmpeg thread and holding the CameraSource lock
|
||||||
// So be careful not to deadlock with anything while toxav locks in toxav_video_send_frame
|
// So be careful not to deadlock with anything while toxav locks in toxav_video_send_frame
|
||||||
if (calls.find(callId) == calls.end()) {
|
auto it = calls.find(callId);
|
||||||
|
if (it == calls.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxFriendCall& call = calls[callId];
|
ToxFriendCall& call = it->second;
|
||||||
|
|
||||||
if (!call.getVideoEnabled() || !call.isActive()
|
if (!call.getVideoEnabled() || !call.isActive()
|
||||||
|| !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V)) {
|
|| !(call.getState() & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V)) {
|
||||||
|
@ -431,8 +444,9 @@ void CoreAV::sendCallVideo(uint32_t callId, std::shared_ptr<VideoFrame> vframe)
|
||||||
*/
|
*/
|
||||||
void CoreAV::toggleMuteCallInput(const Friend* f)
|
void CoreAV::toggleMuteCallInput(const Friend* f)
|
||||||
{
|
{
|
||||||
if (f && (calls.find(f->getId()) != calls.end())) {
|
auto it = calls.find(f->getId());
|
||||||
ToxCall& call = calls[f->getId()];
|
if (f && (it != calls.end())) {
|
||||||
|
ToxCall& call = it->second;
|
||||||
call.setMuteMic(!call.getMuteMic());
|
call.setMuteMic(!call.getMuteMic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,8 +457,9 @@ void CoreAV::toggleMuteCallInput(const Friend* f)
|
||||||
*/
|
*/
|
||||||
void CoreAV::toggleMuteCallOutput(const Friend* f)
|
void CoreAV::toggleMuteCallOutput(const Friend* f)
|
||||||
{
|
{
|
||||||
if (f && (calls.find(f->getId()) != calls.end())) {
|
auto it = calls.find(f->getId());
|
||||||
ToxCall& call = calls[f->getId()];
|
if (f && (it != calls.end())) {
|
||||||
|
ToxCall& call = it->second;
|
||||||
call.setMuteVol(!call.getMuteVol());
|
call.setMuteVol(!call.getMuteVol());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,11 +485,12 @@ void CoreAV::groupCallCallback(void* tox, uint32_t group, uint32_t peer, const i
|
||||||
Core* c = static_cast<Core*>(core);
|
Core* c = static_cast<Core*>(core);
|
||||||
CoreAV* cav = c->getAv();
|
CoreAV* cav = c->getAv();
|
||||||
|
|
||||||
if (cav->groupCalls.find(group) == cav->groupCalls.end()) {
|
auto it = cav->groupCalls.find(group);
|
||||||
|
if (it == cav->groupCalls.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxGroupCall& call = cav->groupCalls[group];
|
ToxGroupCall& call = it->second;
|
||||||
|
|
||||||
emit c->groupPeerAudioPlaying(group, peer);
|
emit c->groupPeerAudioPlaying(group, peer);
|
||||||
|
|
||||||
|
@ -499,11 +515,12 @@ void CoreAV::groupCallCallback(void* tox, int group, int peer, const int16_t* da
|
||||||
Core* c = static_cast<Core*>(core);
|
Core* c = static_cast<Core*>(core);
|
||||||
CoreAV* cav = c->getAv();
|
CoreAV* cav = c->getAv();
|
||||||
|
|
||||||
if (cav->groupCalls.find(group) == cav->groupCalls.end()) {
|
auto it = cav->groupCalls.find(group);
|
||||||
|
if (it == cav->groupCalls.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxGroupCall& call = cav->groupCalls[group];
|
ToxGroupCall& call = it->second;
|
||||||
|
|
||||||
emit c->groupPeerAudioPlaying(group, peer);
|
emit c->groupPeerAudioPlaying(group, peer);
|
||||||
|
|
||||||
|
@ -528,9 +545,13 @@ void CoreAV::groupCallCallback(void* tox, int group, int peer, const int16_t* da
|
||||||
*/
|
*/
|
||||||
void CoreAV::invalidateGroupCallPeerSource(int group, int peer)
|
void CoreAV::invalidateGroupCallPeerSource(int group, int peer)
|
||||||
{
|
{
|
||||||
|
auto it = groupCalls.find(group);
|
||||||
|
if (it == groupCalls.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Audio& audio = Audio::getInstance();
|
Audio& audio = Audio::getInstance();
|
||||||
audio.unsubscribeOutput(groupCalls[group].getPeers()[peer]);
|
audio.unsubscribeOutput(it->second.getPeers()[peer]);
|
||||||
groupCalls[group].getPeers()[peer] = 0;
|
it->second.getPeers()[peer] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -548,15 +569,16 @@ void CoreAV::invalidateGroupCallSources(int group)
|
||||||
* @param friendNum Id of friend in call list.
|
* @param friendNum Id of friend in call list.
|
||||||
* @return Video surface to show
|
* @return Video surface to show
|
||||||
*/
|
*/
|
||||||
VideoSource* CoreAV::getVideoSourceFromCall(int friendNum)
|
VideoSource* CoreAV::getVideoSourceFromCall(int friendNum) const
|
||||||
{
|
{
|
||||||
if (calls.find(friendNum) == calls.end()) {
|
auto it = calls.find(friendNum);
|
||||||
|
if (it == calls.end()) {
|
||||||
qWarning() << "CoreAV::getVideoSourceFromCall: No such call, did it die before we finished "
|
qWarning() << "CoreAV::getVideoSourceFromCall: No such call, did it die before we finished "
|
||||||
"answering?";
|
"answering?";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return calls[friendNum].getVideoSource();
|
return it->second.getVideoSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -568,8 +590,12 @@ void CoreAV::joinGroupCall(int groupId)
|
||||||
{
|
{
|
||||||
qDebug() << QString("Joining group call %1").arg(groupId);
|
qDebug() << QString("Joining group call %1").arg(groupId);
|
||||||
|
|
||||||
groupCalls[groupId] = ToxGroupCall{groupId, *this};
|
auto ret = groupCalls.insert(std::pair<int, ToxGroupCall>(groupId, ToxGroupCall{groupId, *this}));
|
||||||
groupCalls[groupId].setActive(true);
|
if (ret.second == false) {
|
||||||
|
qWarning() << "This group call already exists, not joining!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret.first->second.setActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -585,15 +611,14 @@ void CoreAV::leaveGroupCall(int groupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CoreAV::sendGroupCallAudio(int groupId, const int16_t* pcm, size_t samples, uint8_t chans,
|
bool CoreAV::sendGroupCallAudio(int groupId, const int16_t* pcm, size_t samples, uint8_t chans,
|
||||||
uint32_t rate)
|
uint32_t rate) const
|
||||||
{
|
{
|
||||||
if (groupCalls.find(groupId) == groupCalls.end()) {
|
std::map<int, ToxGroupCall>::const_iterator it = groupCalls.find(groupId);
|
||||||
|
if (it == groupCalls.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxGroupCall& call = groupCalls[groupId];
|
if (!it->second.isActive() || it->second.getMuteMic()) {
|
||||||
|
|
||||||
if (!call.isActive() || call.getMuteMic()) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,8 +635,9 @@ bool CoreAV::sendGroupCallAudio(int groupId, const int16_t* pcm, size_t samples,
|
||||||
*/
|
*/
|
||||||
void CoreAV::muteCallInput(const Group* g, bool mute)
|
void CoreAV::muteCallInput(const Group* g, bool mute)
|
||||||
{
|
{
|
||||||
if (g && (groupCalls.find(g->getId()) != groupCalls.end())) {
|
auto it = groupCalls.find(g->getId());
|
||||||
groupCalls[g->getId()].setMuteMic(mute);
|
if (g && (it != groupCalls.end())) {
|
||||||
|
it->second.setMuteMic(mute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,8 +648,9 @@ void CoreAV::muteCallInput(const Group* g, bool mute)
|
||||||
*/
|
*/
|
||||||
void CoreAV::muteCallOutput(const Group* g, bool mute)
|
void CoreAV::muteCallOutput(const Group* g, bool mute)
|
||||||
{
|
{
|
||||||
if (g && (groupCalls.find(g->getId()) != groupCalls.end())) {
|
auto it = groupCalls.find(g->getId());
|
||||||
groupCalls[g->getId()].setMuteVol(mute);
|
if (g && (it != groupCalls.end())) {
|
||||||
|
it->second.setMuteVol(mute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +666,8 @@ bool CoreAV::isGroupCallInputMuted(const Group* g) const
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t groupId = g->getId();
|
const uint32_t groupId = g->getId();
|
||||||
return (groupCalls.find(groupId) != groupCalls.end()) && groupCalls[groupId].getMuteMic();
|
auto it = groupCalls.find(groupId);
|
||||||
|
return (it != groupCalls.end()) && it->second.getMuteMic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -654,7 +682,8 @@ bool CoreAV::isGroupCallOutputMuted(const Group* g) const
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t groupId = g->getId();
|
const uint32_t groupId = g->getId();
|
||||||
return (groupCalls.find(groupId) != groupCalls.end()) && groupCalls[groupId].getMuteVol();
|
auto it = groupCalls.find(groupId);
|
||||||
|
return (it != groupCalls.end()) && it->second.getMuteVol();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -691,7 +720,8 @@ bool CoreAV::isCallInputMuted(const Friend* f) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint32_t friendId = f->getId();
|
const uint32_t friendId = f->getId();
|
||||||
return (calls.find(friendId) != calls.end()) && calls[friendId].getMuteMic();
|
auto it = calls.find(friendId);
|
||||||
|
return (it != calls.end()) && it->second.getMuteMic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -705,7 +735,8 @@ bool CoreAV::isCallOutputMuted(const Friend* f) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint32_t friendId = f->getId();
|
const uint32_t friendId = f->getId();
|
||||||
return (calls.find(friendId) != calls.end()) && calls[f->getId()].getMuteVol();
|
auto it = calls.find(friendId);
|
||||||
|
return (it != calls.end()) && it->second.getMuteVol();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -763,7 +794,8 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->calls.find(friendNum) != self->calls.end()) {
|
auto it = self->calls.insert(std::pair<uint32_t, ToxFriendCall>(friendNum, ToxFriendCall{friendNum, video, *self}));
|
||||||
|
if (it.second == false) {
|
||||||
/// Hanging up from a callback is supposed to be UB,
|
/// Hanging up from a callback is supposed to be UB,
|
||||||
/// but since currently the toxav callbacks are fired from the toxcore thread,
|
/// but since currently the toxav callbacks are fired from the toxcore thread,
|
||||||
/// we'll always reach this point through a non-blocking queud connection, so not in the
|
/// we'll always reach this point through a non-blocking queud connection, so not in the
|
||||||
|
@ -773,7 +805,6 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << QString("Received call invite from %1").arg(friendNum);
|
qDebug() << QString("Received call invite from %1").arg(friendNum);
|
||||||
self->calls[friendNum] = ToxFriendCall{friendNum, video, *self};
|
|
||||||
|
|
||||||
// We don't get a state callback when answering, so fill the state ourselves in advance
|
// We don't get a state callback when answering, so fill the state ourselves in advance
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
@ -781,7 +812,8 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
|
||||||
state |= TOXAV_FRIEND_CALL_STATE_SENDING_A | TOXAV_FRIEND_CALL_STATE_ACCEPTING_A;
|
state |= TOXAV_FRIEND_CALL_STATE_SENDING_A | TOXAV_FRIEND_CALL_STATE_ACCEPTING_A;
|
||||||
if (video)
|
if (video)
|
||||||
state |= TOXAV_FRIEND_CALL_STATE_SENDING_V | TOXAV_FRIEND_CALL_STATE_ACCEPTING_V;
|
state |= TOXAV_FRIEND_CALL_STATE_SENDING_V | TOXAV_FRIEND_CALL_STATE_ACCEPTING_V;
|
||||||
calls[friendNum].setState(static_cast<TOXAV_FRIEND_CALL_STATE>(state));
|
it.first->second.setState(static_cast<TOXAV_FRIEND_CALL_STATE>(state));
|
||||||
|
// note: changed to self->
|
||||||
|
|
||||||
emit reinterpret_cast<CoreAV*>(self)->avInvite(friendNum, video);
|
emit reinterpret_cast<CoreAV*>(self)->avInvite(friendNum, video);
|
||||||
self->threadSwitchLock.clear(std::memory_order_release);
|
self->threadSwitchLock.clear(std::memory_order_release);
|
||||||
|
@ -808,21 +840,24 @@ void CoreAV::stateCallback(ToxAV* toxav, uint32_t friendNum, uint32_t state, voi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->calls.find(friendNum) == self->calls.end()) {
|
auto it = self->calls.find(friendNum);
|
||||||
|
if (it == self->calls.end()) {
|
||||||
qWarning() << QString("stateCallback called, but call %1 is already dead").arg(friendNum);
|
qWarning() << QString("stateCallback called, but call %1 is already dead").arg(friendNum);
|
||||||
self->threadSwitchLock.clear(std::memory_order_release);
|
self->threadSwitchLock.clear(std::memory_order_release);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxFriendCall& call = self->calls[friendNum];
|
ToxFriendCall& call = it->second;
|
||||||
|
|
||||||
if (state & TOXAV_FRIEND_CALL_STATE_ERROR) {
|
if (state & TOXAV_FRIEND_CALL_STATE_ERROR) {
|
||||||
qWarning() << "Call with friend" << friendNum << "died of unnatural causes!";
|
qWarning() << "Call with friend" << friendNum << "died of unnatural causes!";
|
||||||
calls.erase(friendNum);
|
calls.erase(friendNum);
|
||||||
|
// why not self->
|
||||||
emit self->avEnd(friendNum, true);
|
emit self->avEnd(friendNum, true);
|
||||||
} else if (state & TOXAV_FRIEND_CALL_STATE_FINISHED) {
|
} else if (state & TOXAV_FRIEND_CALL_STATE_FINISHED) {
|
||||||
qDebug() << "Call with friend" << friendNum << "finished quietly";
|
qDebug() << "Call with friend" << friendNum << "finished quietly";
|
||||||
calls.erase(friendNum);
|
calls.erase(friendNum);
|
||||||
|
// why not self->
|
||||||
emit self->avEnd(friendNum);
|
emit self->avEnd(friendNum);
|
||||||
} else {
|
} else {
|
||||||
// If our state was null, we started the call and were still ringing
|
// If our state was null, we started the call and were still ringing
|
||||||
|
@ -904,11 +939,12 @@ void CoreAV::audioFrameCallback(ToxAV*, uint32_t friendNum, const int16_t* pcm,
|
||||||
uint8_t channels, uint32_t samplingRate, void* vSelf)
|
uint8_t channels, uint32_t samplingRate, void* vSelf)
|
||||||
{
|
{
|
||||||
CoreAV* self = static_cast<CoreAV*>(vSelf);
|
CoreAV* self = static_cast<CoreAV*>(vSelf);
|
||||||
if (self->calls.find(friendNum) == self->calls.end()) {
|
auto it = calls.find(friendNum);
|
||||||
|
if (it == self->calls.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxFriendCall& call = self->calls[friendNum];
|
ToxFriendCall& call = it->second;
|
||||||
|
|
||||||
if (call.getMuteVol()) {
|
if (call.getMuteVol()) {
|
||||||
return;
|
return;
|
||||||
|
@ -928,11 +964,12 @@ void CoreAV::videoFrameCallback(ToxAV*, uint32_t friendNum, uint16_t w, uint16_t
|
||||||
const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
||||||
int32_t ystride, int32_t ustride, int32_t vstride, void*)
|
int32_t ystride, int32_t ustride, int32_t vstride, void*)
|
||||||
{
|
{
|
||||||
if (calls.find(friendNum) == calls.end()) {
|
auto it = calls.find(friendNum);
|
||||||
|
if (it == calls.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreVideoSource* videoSource = calls[friendNum].getVideoSource();
|
CoreVideoSource* videoSource = it->second.getVideoSource();
|
||||||
if (!videoSource) {
|
if (!videoSource) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,12 @@ public:
|
||||||
bool isCallActive(const Group* g) const;
|
bool isCallActive(const Group* g) const;
|
||||||
bool isCallVideoEnabled(const Friend* f) const;
|
bool isCallVideoEnabled(const Friend* f) const;
|
||||||
bool sendCallAudio(uint32_t friendNum, const int16_t* pcm, size_t samples, uint8_t chans,
|
bool sendCallAudio(uint32_t friendNum, const int16_t* pcm, size_t samples, uint8_t chans,
|
||||||
uint32_t rate);
|
uint32_t rate) const;
|
||||||
void sendCallVideo(uint32_t friendNum, std::shared_ptr<VideoFrame> frame);
|
void sendCallVideo(uint32_t friendNum, std::shared_ptr<VideoFrame> frame);
|
||||||
bool sendGroupCallAudio(int groupNum, const int16_t* pcm, size_t samples, uint8_t chans,
|
bool sendGroupCallAudio(int groupNum, const int16_t* pcm, size_t samples, uint8_t chans,
|
||||||
uint32_t rate);
|
uint32_t rate) const;
|
||||||
|
|
||||||
VideoSource* getVideoSourceFromCall(int callNumber);
|
VideoSource* getVideoSourceFromCall(int callNumber) const;
|
||||||
void invalidateCallSources();
|
void invalidateCallSources();
|
||||||
void sendNoVideo();
|
void sendNoVideo();
|
||||||
|
|
||||||
|
|
|
@ -28,55 +28,111 @@
|
||||||
* @brief Keeps sources for users in group calls.
|
* @brief Keeps sources for users in group calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using namespace std;
|
ToxCall::ToxCall(uint32_t CallId, bool VideoEnabled, CoreAV& av)
|
||||||
|
: videoEnabled{VideoEnabled}
|
||||||
ToxCall::ToxCall()
|
, av{&av}
|
||||||
: active{false}
|
|
||||||
, muteMic{false}
|
|
||||||
, muteVol{false}
|
|
||||||
{
|
{
|
||||||
Audio& audio = Audio::getInstance();
|
Audio& audio = Audio::getInstance();
|
||||||
audio.subscribeInput();
|
audio.subscribeInput();
|
||||||
|
audio.subscribeOutput(alSource);
|
||||||
|
|
||||||
|
audioInConn = QObject::connect(&Audio::getInstance(), &Audio::frameAvailable,
|
||||||
|
[&av, CallId](const int16_t* pcm, size_t samples, uint8_t chans,
|
||||||
|
uint32_t rate) {
|
||||||
|
av.sendCallAudio(CallId, pcm, samples, chans, rate);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!audioInConn) {
|
||||||
|
qDebug() << "Audio connection not working";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoEnabled) {
|
||||||
|
videoSource = new CoreVideoSource();
|
||||||
|
CameraSource& source = CameraSource::getInstance();
|
||||||
|
|
||||||
|
if (source.isNone()) {
|
||||||
|
source.setupDefault();
|
||||||
|
}
|
||||||
|
source.subscribe();
|
||||||
|
videoInConn = QObject::connect(&source, &VideoSource::frameAvailable,
|
||||||
|
[&av, CallId](std::shared_ptr<VideoFrame> frame) {
|
||||||
|
av.sendCallVideo(CallId, frame);
|
||||||
|
});
|
||||||
|
if (!videoInConn) {
|
||||||
|
qDebug() << "Video connection not working";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxCall::ToxCall(ToxCall&& other) noexcept
|
ToxCall::ToxCall(ToxCall&& other) noexcept : audioInConn{other.audioInConn},
|
||||||
: audioInConn{other.audioInConn}
|
alSource{other.alSource},
|
||||||
, active{other.active}
|
active{other.active},
|
||||||
, muteMic{other.muteMic}
|
muteMic{other.muteMic},
|
||||||
, muteVol{other.muteVol}
|
muteVol{other.muteVol},
|
||||||
|
videoInConn{other.videoInConn},
|
||||||
|
videoEnabled{other.videoEnabled},
|
||||||
|
nullVideoBitrate{other.nullVideoBitrate},
|
||||||
|
videoSource{other.videoSource},
|
||||||
|
av{other.av}
|
||||||
{
|
{
|
||||||
|
Audio& audio = Audio::getInstance();
|
||||||
|
audio.subscribeInput();
|
||||||
other.audioInConn = QMetaObject::Connection();
|
other.audioInConn = QMetaObject::Connection();
|
||||||
// invalidate object, all resources are moved
|
other.alSource = 0;
|
||||||
other.valid = false;
|
other.videoInConn = QMetaObject::Connection();
|
||||||
|
other.videoEnabled = false; // we don't need to subscribe video because other won't unsubscribe
|
||||||
|
other.videoSource = nullptr;
|
||||||
|
other.av = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxCall::~ToxCall()
|
ToxCall::~ToxCall()
|
||||||
{
|
{
|
||||||
Audio& audio = Audio::getInstance();
|
Audio& audio = Audio::getInstance();
|
||||||
|
|
||||||
// only free resources if they weren't moved
|
QObject::disconnect(audioInConn);
|
||||||
if (valid) {
|
audio.unsubscribeInput();
|
||||||
QObject::disconnect(audioInConn);
|
audio.unsubscribeOutput(alSource);
|
||||||
audio.unsubscribeInput();
|
if (videoEnabled) {
|
||||||
|
QObject::disconnect(videoInConn);
|
||||||
|
CameraSource::getInstance().unsubscribe();
|
||||||
|
// TODO: check if async is still needed
|
||||||
|
// This destructor could be running in a toxav callback while holding toxav locks.
|
||||||
|
// If the CameraSource thread calls toxav *_send_frame, we might deadlock the toxav and
|
||||||
|
// CameraSource locks,
|
||||||
|
// so we unsuscribe asynchronously, it's fine if the webcam takes a couple milliseconds more
|
||||||
|
// to poweroff.
|
||||||
|
QtConcurrent::run([]() { CameraSource::getInstance().unsubscribe(); });
|
||||||
|
if (videoSource) {
|
||||||
|
videoSource->setDeleteOnClose(true);
|
||||||
|
videoSource = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxCall& ToxCall::operator=(ToxCall&& other) noexcept
|
ToxCall& ToxCall::operator=(ToxCall&& other) noexcept
|
||||||
{
|
{
|
||||||
if (valid) {
|
QObject::disconnect(audioInConn);
|
||||||
// if we're already valid, we need to cleanup our resources since we're going to inherit the resources
|
|
||||||
// that are being moved in
|
|
||||||
QObject::disconnect(audioInConn);
|
|
||||||
Audio::getInstance().unsubscribeInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
audioInConn = other.audioInConn;
|
audioInConn = other.audioInConn;
|
||||||
other.audioInConn = QMetaObject::Connection();
|
other.audioInConn = QMetaObject::Connection();
|
||||||
active = other.active;
|
active = other.active;
|
||||||
muteMic = other.muteMic;
|
muteMic = other.muteMic;
|
||||||
muteVol = other.muteVol;
|
muteVol = other.muteVol;
|
||||||
// invalidate object, all resources are moved
|
|
||||||
other.valid = false;
|
alSource = other.alSource;
|
||||||
|
other.alSource = 0;
|
||||||
|
|
||||||
|
Audio::getInstance().subscribeInput();
|
||||||
|
|
||||||
|
videoInConn = other.videoInConn;
|
||||||
|
other.videoInConn = QMetaObject::Connection();
|
||||||
|
videoEnabled = other.videoEnabled;
|
||||||
|
other.videoEnabled = false;
|
||||||
|
nullVideoBitrate = other.nullVideoBitrate;
|
||||||
|
videoSource = other.videoSource;
|
||||||
|
other.videoSource = nullptr;
|
||||||
|
av = other.av;
|
||||||
|
other.av = nullptr;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -111,13 +167,53 @@ void ToxCall::setMuteMic(bool value)
|
||||||
muteMic = value;
|
muteMic = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ToxCall::getVideoEnabled() const
|
||||||
|
{
|
||||||
|
return videoEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToxCall::setVideoEnabled(bool value)
|
||||||
|
{
|
||||||
|
videoEnabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ToxCall::getNullVideoBitrate() const
|
||||||
|
{
|
||||||
|
return nullVideoBitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToxCall::setNullVideoBitrate(bool value)
|
||||||
|
{
|
||||||
|
nullVideoBitrate = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreVideoSource* ToxCall::getVideoSource() const
|
||||||
|
{
|
||||||
|
return videoSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 ToxCall::getAlSource() const
|
||||||
|
{
|
||||||
|
return alSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToxCall::setAlSource(const quint32& value)
|
||||||
|
{
|
||||||
|
alSource = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av)
|
||||||
|
: ToxCall(FriendNum, VideoEnabled, av)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ToxFriendCall::startTimeout(uint32_t callId)
|
void ToxFriendCall::startTimeout(uint32_t callId)
|
||||||
{
|
{
|
||||||
if (!timeoutTimer) {
|
if (!timeoutTimer) {
|
||||||
timeoutTimer = new QTimer();
|
timeoutTimer = std::unique_ptr<QTimer>{new QTimer{}};
|
||||||
// We might move, so we need copies of members. CoreAV won't move while we're alive
|
// We might move, so we need copies of members. CoreAV won't move while we're alive
|
||||||
CoreAV* avCopy = av;
|
CoreAV* avCopy = av;
|
||||||
QObject::connect(timeoutTimer, &QTimer::timeout,
|
QObject::connect(timeoutTimer.get(), &QTimer::timeout,
|
||||||
[avCopy, callId]() { avCopy->timeoutCall(callId); });
|
[avCopy, callId]() { avCopy->timeoutCall(callId); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,33 +227,7 @@ void ToxFriendCall::stopTimeout()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
timeoutTimer->stop();
|
timeoutTimer->stop();
|
||||||
delete timeoutTimer;
|
timeoutTimer.reset();
|
||||||
timeoutTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ToxFriendCall::getVideoEnabled() const
|
|
||||||
{
|
|
||||||
return videoEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ToxFriendCall::setVideoEnabled(bool value)
|
|
||||||
{
|
|
||||||
videoEnabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ToxFriendCall::getNullVideoBitrate() const
|
|
||||||
{
|
|
||||||
return nullVideoBitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ToxFriendCall::setNullVideoBitrate(bool value)
|
|
||||||
{
|
|
||||||
nullVideoBitrate = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreVideoSource* ToxFriendCall::getVideoSource() const
|
|
||||||
{
|
|
||||||
return videoSource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TOXAV_FRIEND_CALL_STATE ToxFriendCall::getState() const
|
TOXAV_FRIEND_CALL_STATE ToxFriendCall::getState() const
|
||||||
|
@ -170,127 +240,12 @@ void ToxFriendCall::setState(const TOXAV_FRIEND_CALL_STATE& value)
|
||||||
state = value;
|
state = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 ToxFriendCall::getAlSource() const
|
|
||||||
{
|
|
||||||
return alSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ToxFriendCall::setAlSource(const quint32& value)
|
|
||||||
{
|
|
||||||
alSource = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ToxFriendCall::ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av)
|
|
||||||
: ToxCall()
|
|
||||||
, videoEnabled{VideoEnabled}
|
|
||||||
, nullVideoBitrate{false}
|
|
||||||
, videoSource{nullptr}
|
|
||||||
, state{static_cast<TOXAV_FRIEND_CALL_STATE>(0)}
|
|
||||||
, av{&av}
|
|
||||||
, timeoutTimer{nullptr}
|
|
||||||
{
|
|
||||||
Audio& audio = Audio::getInstance();
|
|
||||||
audioInConn = QObject::connect(&audio, &Audio::frameAvailable,
|
|
||||||
[&av, friendId](const int16_t* pcm, size_t samples,
|
|
||||||
uint8_t chans, uint32_t rate) {
|
|
||||||
av.sendCallAudio(friendId, pcm, samples, chans, rate);
|
|
||||||
});
|
|
||||||
if (!audioInConn) {
|
|
||||||
qDebug() << "Audio connection not working";
|
|
||||||
}
|
|
||||||
|
|
||||||
// subscribe audio output
|
|
||||||
audio.subscribeOutput(alSource);
|
|
||||||
|
|
||||||
if (videoEnabled) {
|
|
||||||
videoSource = new CoreVideoSource;
|
|
||||||
CameraSource& source = CameraSource::getInstance();
|
|
||||||
|
|
||||||
if (source.isNone())
|
|
||||||
source.setupDefault();
|
|
||||||
source.subscribe();
|
|
||||||
QObject::connect(&source, &VideoSource::frameAvailable,
|
|
||||||
[friendId, &av](shared_ptr<VideoFrame> frame) {
|
|
||||||
av.sendCallVideo(friendId, frame);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ToxFriendCall::ToxFriendCall(ToxFriendCall&& other) noexcept
|
|
||||||
: ToxCall(move(other))
|
|
||||||
, alSource{other.alSource}
|
|
||||||
, videoEnabled{other.videoEnabled}
|
|
||||||
, nullVideoBitrate{other.nullVideoBitrate}
|
|
||||||
, videoSource{other.videoSource}
|
|
||||||
, state{other.state}
|
|
||||||
, av{other.av}
|
|
||||||
, timeoutTimer{other.timeoutTimer}
|
|
||||||
{
|
|
||||||
other.videoEnabled = false;
|
|
||||||
other.videoSource = nullptr;
|
|
||||||
other.timeoutTimer = nullptr;
|
|
||||||
// TODO: wrong, because "0" could be a valid source id
|
|
||||||
other.alSource = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ToxFriendCall::~ToxFriendCall()
|
|
||||||
{
|
|
||||||
if (timeoutTimer)
|
|
||||||
delete timeoutTimer;
|
|
||||||
|
|
||||||
if (videoEnabled) {
|
|
||||||
// This destructor could be running in a toxav callback while holding toxav locks.
|
|
||||||
// If the CameraSource thread calls toxav *_send_frame, we might deadlock the toxav and
|
|
||||||
// CameraSource locks,
|
|
||||||
// so we unsuscribe asynchronously, it's fine if the webcam takes a couple milliseconds more
|
|
||||||
// to poweroff.
|
|
||||||
QtConcurrent::run([]() { CameraSource::getInstance().unsubscribe(); });
|
|
||||||
if (videoSource) {
|
|
||||||
videoSource->setDeleteOnClose(true);
|
|
||||||
videoSource = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (valid) {
|
|
||||||
Audio::getInstance().unsubscribeOutput(alSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ToxFriendCall& ToxFriendCall::operator=(ToxFriendCall&& other) noexcept
|
|
||||||
{
|
|
||||||
ToxCall::operator=(move(other));
|
|
||||||
videoEnabled = other.videoEnabled;
|
|
||||||
other.videoEnabled = false;
|
|
||||||
videoSource = other.videoSource;
|
|
||||||
other.videoSource = nullptr;
|
|
||||||
state = other.state;
|
|
||||||
timeoutTimer = other.timeoutTimer;
|
|
||||||
other.timeoutTimer = nullptr;
|
|
||||||
av = other.av;
|
|
||||||
nullVideoBitrate = other.nullVideoBitrate;
|
|
||||||
alSource = other.alSource;
|
|
||||||
// TODO: wrong, because "0" could be a valid source id
|
|
||||||
other.alSource = 0;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ToxGroupCall::ToxGroupCall(int GroupNum, CoreAV& av)
|
ToxGroupCall::ToxGroupCall(int GroupNum, CoreAV& av)
|
||||||
: ToxCall()
|
: ToxCall(static_cast<uint32_t>(GroupNum), false, av)
|
||||||
{
|
{
|
||||||
static_assert(
|
|
||||||
numeric_limits<uint32_t>::max() >= numeric_limits<decltype(GroupNum)>::max(),
|
|
||||||
"The callId must be able to represent any group number, change its type if needed");
|
|
||||||
|
|
||||||
audioInConn = QObject::connect(&Audio::getInstance(), &Audio::frameAvailable,
|
|
||||||
[&av, GroupNum](const int16_t* pcm, size_t samples,
|
|
||||||
uint8_t chans, uint32_t rate) {
|
|
||||||
av.sendGroupCallAudio(GroupNum, pcm, samples, chans, rate);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxGroupCall::ToxGroupCall(ToxGroupCall&& other) noexcept
|
ToxGroupCall::ToxGroupCall(ToxGroupCall&& other) noexcept : ToxCall(std::move(other)), peers{other.peers}
|
||||||
: ToxCall(move(other))
|
|
||||||
, peers{other.peers}
|
|
||||||
{
|
{
|
||||||
// all peers were moved, this ensures audio output is unsubscribed only once
|
// all peers were moved, this ensures audio output is unsubscribed only once
|
||||||
other.peers.clear();
|
other.peers.clear();
|
||||||
|
@ -307,7 +262,7 @@ ToxGroupCall::~ToxGroupCall()
|
||||||
|
|
||||||
ToxGroupCall& ToxGroupCall::operator=(ToxGroupCall&& other) noexcept
|
ToxGroupCall& ToxGroupCall::operator=(ToxGroupCall&& other) noexcept
|
||||||
{
|
{
|
||||||
ToxCall::operator=(move(other));
|
ToxCall::operator=(std::move(other));
|
||||||
peers = other.peers;
|
peers = other.peers;
|
||||||
other.peers.clear();
|
other.peers.clear();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef TOXCALL_H
|
#ifndef TOXCALL_H
|
||||||
#define TOXCALL_H
|
#define TOXCALL_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
@ -16,7 +17,8 @@ class CoreAV;
|
||||||
class ToxCall
|
class ToxCall
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
explicit ToxCall();
|
ToxCall() = delete;
|
||||||
|
ToxCall(uint32_t CallId, bool VideoEnabled, CoreAV& av);
|
||||||
~ToxCall();
|
~ToxCall();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -26,7 +28,6 @@ public:
|
||||||
ToxCall& operator=(const ToxCall& other) = delete;
|
ToxCall& operator=(const ToxCall& other) = delete;
|
||||||
ToxCall& operator=(ToxCall&& other) noexcept;
|
ToxCall& operator=(ToxCall&& other) noexcept;
|
||||||
|
|
||||||
bool isInactive() const;
|
|
||||||
bool isActive() const;
|
bool isActive() const;
|
||||||
void setActive(bool value);
|
void setActive(bool value);
|
||||||
|
|
||||||
|
@ -36,27 +37,6 @@ public:
|
||||||
bool getMuteMic() const;
|
bool getMuteMic() const;
|
||||||
void setMuteMic(bool value);
|
void setMuteMic(bool value);
|
||||||
|
|
||||||
protected:
|
|
||||||
QMetaObject::Connection audioInConn;
|
|
||||||
bool active;
|
|
||||||
bool muteMic;
|
|
||||||
bool muteVol;
|
|
||||||
bool valid = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ToxFriendCall : public ToxCall
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ToxFriendCall() = default;
|
|
||||||
ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av);
|
|
||||||
ToxFriendCall(ToxFriendCall&& other) noexcept;
|
|
||||||
~ToxFriendCall();
|
|
||||||
|
|
||||||
ToxFriendCall& operator=(ToxFriendCall&& other) noexcept;
|
|
||||||
|
|
||||||
void startTimeout(uint32_t callId);
|
|
||||||
void stopTimeout();
|
|
||||||
|
|
||||||
bool getVideoEnabled() const;
|
bool getVideoEnabled() const;
|
||||||
void setVideoEnabled(bool value);
|
void setVideoEnabled(bool value);
|
||||||
|
|
||||||
|
@ -65,31 +45,50 @@ public:
|
||||||
|
|
||||||
CoreVideoSource* getVideoSource() const;
|
CoreVideoSource* getVideoSource() const;
|
||||||
|
|
||||||
TOXAV_FRIEND_CALL_STATE getState() const;
|
|
||||||
void setState(const TOXAV_FRIEND_CALL_STATE& value);
|
|
||||||
|
|
||||||
quint32 getAlSource() const;
|
quint32 getAlSource() const;
|
||||||
void setAlSource(const quint32& value);
|
void setAlSource(const quint32& value);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
quint32 alSource;
|
bool active{false};
|
||||||
bool videoEnabled;
|
CoreAV* av{nullptr};
|
||||||
bool nullVideoBitrate;
|
// audio
|
||||||
CoreVideoSource* videoSource;
|
QMetaObject::Connection audioInConn;
|
||||||
TOXAV_FRIEND_CALL_STATE state;
|
bool muteMic{false};
|
||||||
|
bool muteVol{false};
|
||||||
|
quint32 alSource{0};
|
||||||
|
// video
|
||||||
|
CoreVideoSource* videoSource{nullptr};
|
||||||
|
QMetaObject::Connection videoInConn;
|
||||||
|
bool videoEnabled{false};
|
||||||
|
bool nullVideoBitrate{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ToxFriendCall : public ToxCall
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ToxFriendCall() = delete;
|
||||||
|
ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av);
|
||||||
|
ToxFriendCall(ToxFriendCall&& other) noexcept = default;
|
||||||
|
ToxFriendCall& operator=(ToxFriendCall&& other) noexcept = default;
|
||||||
|
|
||||||
|
void startTimeout(uint32_t callId);
|
||||||
|
void stopTimeout();
|
||||||
|
|
||||||
|
TOXAV_FRIEND_CALL_STATE getState() const;
|
||||||
|
void setState(const TOXAV_FRIEND_CALL_STATE& value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CoreAV* av;
|
std::unique_ptr<QTimer> timeoutTimer;
|
||||||
QTimer* timeoutTimer;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TOXAV_FRIEND_CALL_STATE state{TOXAV_FRIEND_CALL_STATE_NONE};
|
||||||
static constexpr int CALL_TIMEOUT = 45000;
|
static constexpr int CALL_TIMEOUT = 45000;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ToxGroupCall : public ToxCall
|
class ToxGroupCall : public ToxCall
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ToxGroupCall() = default;
|
ToxGroupCall() = delete;
|
||||||
ToxGroupCall(int GroupNum, CoreAV& av);
|
ToxGroupCall(int GroupNum, CoreAV& av);
|
||||||
ToxGroupCall(ToxGroupCall&& other) noexcept;
|
ToxGroupCall(ToxGroupCall&& other) noexcept;
|
||||||
~ToxGroupCall();
|
~ToxGroupCall();
|
||||||
|
|
|
@ -50,7 +50,7 @@ private:
|
||||||
std::atomic_bool stopped;
|
std::atomic_bool stopped;
|
||||||
|
|
||||||
friend class CoreAV;
|
friend class CoreAV;
|
||||||
friend class ToxFriendCall;
|
friend class ToxCall;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COREVIDEOSOURCE_H
|
#endif // COREVIDEOSOURCE_H
|
||||||
|
|
Loading…
Reference in New Issue
Block a user