mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Strip out old AV code
This commit is contained in:
parent
bcca4537d5
commit
dbbc702c60
|
@ -29,10 +29,12 @@
|
|||
#include "audio.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/persistence/settings.h"
|
||||
#include "src/core/coreav.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
@ -110,7 +112,7 @@ void Audio::setOutputVolume(qreal volume)
|
|||
outputVolume = volume;
|
||||
alSourcef(alMainSource, AL_GAIN, outputVolume);
|
||||
|
||||
for (const ToxGroupCall& call : Core::groupCalls)
|
||||
for (const ToxGroupCall& call : CoreAV::groupCalls)
|
||||
{
|
||||
if (!call.active)
|
||||
continue;
|
||||
|
@ -118,7 +120,7 @@ void Audio::setOutputVolume(qreal volume)
|
|||
alSourcef(source, AL_GAIN, outputVolume);
|
||||
}
|
||||
|
||||
for (const ToxCall& call : Core::calls)
|
||||
for (const ToxCall& call : CoreAV::calls)
|
||||
{
|
||||
if (!call.active)
|
||||
continue;
|
||||
|
@ -193,10 +195,11 @@ void Audio::openInput(const QString& inDevDescr)
|
|||
}
|
||||
alInDev = nullptr;
|
||||
|
||||
int stereoFlag = av_DefaultSettings.audio_channels==1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||
const uint32_t sampleRate = av_DefaultSettings.audio_sample_rate;
|
||||
const uint16_t frameDuration = av_DefaultSettings.audio_frame_duration;
|
||||
const uint32_t chnls = av_DefaultSettings.audio_channels;
|
||||
/// TODO: Try to actually detect if our audio source is stereo
|
||||
int stereoFlag = DefaultSettings::audioChannels ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||
const uint32_t sampleRate = DefaultSettings::sampleRate;
|
||||
const uint16_t frameDuration = DefaultSettings::frameDuration;
|
||||
const uint32_t chnls = DefaultSettings::audioChannels;
|
||||
const ALCsizei bufSize = (frameDuration * sampleRate * 4) / 1000 * chnls;
|
||||
if (inDevDescr.isEmpty())
|
||||
alInDev = alcCaptureOpenDevice(nullptr, sampleRate, stereoFlag, bufSize);
|
||||
|
@ -211,7 +214,7 @@ void Audio::openInput(const QString& inDevDescr)
|
|||
|
||||
Core* core = Core::getInstance();
|
||||
if (core)
|
||||
core->resetCallSources(); // Force to regen each group call's sources
|
||||
CoreAV::resetCallSources(); // Force to regen each group call's sources
|
||||
|
||||
// Restart the capture if necessary
|
||||
if (alInDev)
|
||||
|
@ -269,7 +272,7 @@ bool Audio::openOutput(const QString &outDevDescr)
|
|||
|
||||
Core* core = Core::getInstance();
|
||||
if (core)
|
||||
core->resetCallSources(); // Force to regen each group call's sources
|
||||
CoreAV::resetCallSources(); // Force to regen each group call's sources
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -371,7 +374,7 @@ void Audio::playMono16Sound(const QByteArray& data)
|
|||
|
||||
The first and last argument are ignored, but allow direct compatibility with toxcore.
|
||||
*/
|
||||
void Audio::playGroupAudioQueued(Tox*,int group, int peer, const int16_t* data,
|
||||
void Audio::playGroupAudioQueued(void*,int group, int peer, const int16_t* data,
|
||||
unsigned samples, uint8_t channels, unsigned sample_rate, void* core)
|
||||
{
|
||||
QMetaObject::invokeMethod(instance, "playGroupAudio", Qt::BlockingQueuedConnection,
|
||||
|
@ -391,7 +394,7 @@ void Audio::playGroupAudio(int group, int peer, const int16_t* data,
|
|||
assert(QThread::currentThread() == audioThread);
|
||||
QMutexLocker lock(&audioOutLock);
|
||||
|
||||
ToxGroupCall& call = Core::groupCalls[group];
|
||||
ToxGroupCall& call = CoreAV::groupCalls[group];
|
||||
|
||||
if (!call.active || call.muteVol)
|
||||
return;
|
||||
|
@ -482,7 +485,7 @@ bool Audio::tryCaptureSamples(uint8_t* buf, int framesize)
|
|||
if (samples < framesize)
|
||||
return false;
|
||||
|
||||
memset(buf, 0, framesize * 2 * av_DefaultSettings.audio_channels); // Avoid uninitialized values (Valgrind)
|
||||
memset(buf, 0, framesize * 2 * DefaultSettings::audioChannels); // Avoid uninitialized values (Valgrind)
|
||||
alcCaptureSamples(Audio::alInDev, buf, framesize);
|
||||
|
||||
if (inputVolume != 1)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define AUDIO_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QMutexLocker>
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
|
@ -34,7 +35,11 @@
|
|||
#include <AL/alc.h>
|
||||
#endif
|
||||
|
||||
class QString;
|
||||
class QByteArray;
|
||||
class QTimer;
|
||||
class QThread;
|
||||
class QMutex;
|
||||
struct Tox;
|
||||
class AudioFilterer;
|
||||
|
||||
|
@ -64,7 +69,7 @@ public:
|
|||
void playMono16Sound(const QByteArray& data);
|
||||
bool tryCaptureSamples(uint8_t* buf, int framesize);
|
||||
|
||||
static void playGroupAudioQueued(Tox*, int group, int peer, const int16_t* data,
|
||||
static void playGroupAudioQueued(void *, int group, int peer, const int16_t* data,
|
||||
unsigned samples, uint8_t channels, unsigned sample_rate, void*);
|
||||
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
|
@ -102,6 +107,12 @@ private:
|
|||
ALuint alMainSource;
|
||||
ALCcontext* alContext;
|
||||
QTimer* timer;
|
||||
|
||||
struct DefaultSettings {
|
||||
static constexpr int sampleRate = 48000;
|
||||
static constexpr int frameDuration = 20;
|
||||
static constexpr int audioChannels = 1;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // AUDIO_H
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "src/nexus.h"
|
||||
#include "src/core/cdata.h"
|
||||
#include "src/core/cstring.h"
|
||||
#include "src/core/coreav.h"
|
||||
#include "src/persistence/settings.h"
|
||||
#include "src/widget/gui.h"
|
||||
#include "src/persistence/historykeeper.h"
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "src/video/camerasource.h"
|
||||
|
||||
#include <tox/tox.h>
|
||||
#include <tox/toxav.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
|
@ -54,32 +56,23 @@
|
|||
|
||||
const QString Core::CONFIG_FILE_NAME = "data";
|
||||
const QString Core::TOX_EXT = ".tox";
|
||||
QHash<int, ToxGroupCall> Core::groupCalls;
|
||||
QThread* Core::coreThread{nullptr};
|
||||
|
||||
#define MAX_GROUP_MESSAGE_LEN 1024
|
||||
|
||||
Core::Core(QThread *CoreThread, Profile& profile) :
|
||||
tox(nullptr), toxav(nullptr), profile(profile), ready{false}
|
||||
tox(nullptr), toxav(nullptr), av(new CoreAV), profile(profile), ready{false}
|
||||
{
|
||||
coreThread = CoreThread;
|
||||
|
||||
Audio::getInstance();
|
||||
|
||||
videobuf = nullptr;
|
||||
|
||||
toxTimer = new QTimer(this);
|
||||
toxTimer->setSingleShot(true);
|
||||
connect(toxTimer, &QTimer::timeout, this, &Core::process);
|
||||
connect(&Settings::getInstance(), &Settings::dhtServerListChanged, this, &Core::process);
|
||||
|
||||
for (int i=0; i<TOXAV_MAX_CALLS;i++)
|
||||
{
|
||||
calls[i].active = false;
|
||||
calls[i].alSource = 0;
|
||||
calls[i].sendAudioTimer = new QTimer();
|
||||
calls[i].sendAudioTimer->moveToThread(coreThread);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::deadifyTox()
|
||||
|
@ -113,18 +106,10 @@ Core::~Core()
|
|||
coreThread->wait(500);
|
||||
}
|
||||
|
||||
for (ToxCall call : calls)
|
||||
{
|
||||
if (!call.active)
|
||||
continue;
|
||||
hangupCall(call.callId);
|
||||
}
|
||||
delete av;
|
||||
|
||||
deadifyTox();
|
||||
|
||||
delete[] videobuf;
|
||||
videobuf=nullptr;
|
||||
|
||||
Audio& audio = Audio::getInstance();
|
||||
audio.closeInput();
|
||||
audio.closeOutput();
|
||||
|
@ -135,6 +120,11 @@ Core* Core::getInstance()
|
|||
return Nexus::getCore();
|
||||
}
|
||||
|
||||
const CoreAV *Core::getAv() const
|
||||
{
|
||||
return av;
|
||||
}
|
||||
|
||||
void Core::makeTox(QByteArray savedata)
|
||||
{
|
||||
// IPv6 needed for LAN discovery, but can crash some weird routers. On by default, can be disabled in options.
|
||||
|
@ -233,7 +223,7 @@ void Core::makeTox(QByteArray savedata)
|
|||
return;
|
||||
}
|
||||
|
||||
toxav = toxav_new(tox, TOXAV_MAX_CALLS);
|
||||
toxav = toxav_new(tox, nullptr);
|
||||
if (toxav == nullptr)
|
||||
{
|
||||
qCritical() << "Toxav core failed to start";
|
||||
|
@ -310,20 +300,6 @@ void Core::start()
|
|||
tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback, this);
|
||||
tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback, this);
|
||||
|
||||
toxav_register_callstate_callback(toxav, onAvInvite, av_OnInvite, this);
|
||||
toxav_register_callstate_callback(toxav, onAvStart, av_OnStart, this);
|
||||
toxav_register_callstate_callback(toxav, onAvCancel, av_OnCancel, this);
|
||||
toxav_register_callstate_callback(toxav, onAvReject, av_OnReject, this);
|
||||
toxav_register_callstate_callback(toxav, onAvEnd, av_OnEnd, this);
|
||||
toxav_register_callstate_callback(toxav, onAvRinging, av_OnRinging, this);
|
||||
toxav_register_callstate_callback(toxav, onAvMediaChange, av_OnPeerCSChange, this);
|
||||
toxav_register_callstate_callback(toxav, onAvMediaChange, av_OnSelfCSChange, this);
|
||||
toxav_register_callstate_callback(toxav, onAvRequestTimeout, av_OnRequestTimeout, this);
|
||||
toxav_register_callstate_callback(toxav, onAvPeerTimeout, av_OnPeerTimeout, this);
|
||||
|
||||
toxav_register_audio_callback(toxav, playCallAudio, this);
|
||||
toxav_register_video_callback(toxav, playCallVideo, this);
|
||||
|
||||
HistoryKeeper::getInstance()->importAvatarToDatabase(getSelfId().toString().left(64));
|
||||
QPixmap pic = Settings::getInstance().getSavedAvatar(getSelfId().toString());
|
||||
if (!pic.isNull() && !pic.size().isEmpty())
|
||||
|
@ -374,7 +350,7 @@ void Core::process()
|
|||
|
||||
static int tolerance = CORE_DISCONNECT_TOLERANCE;
|
||||
tox_iterate(tox);
|
||||
toxav_do(toxav);
|
||||
toxav_iterate(toxav); ///< TODO: This is best called in a separate thread, as per the doc.
|
||||
|
||||
#ifdef DEBUG
|
||||
//we want to see the debug messages immediately
|
||||
|
@ -391,7 +367,7 @@ void Core::process()
|
|||
tolerance = 3*CORE_DISCONNECT_TOLERANCE;
|
||||
}
|
||||
|
||||
unsigned sleeptime = qMin(tox_iteration_interval(tox), toxav_do_interval(toxav));
|
||||
unsigned sleeptime = qMin(tox_iteration_interval(tox), toxav_iteration_interval(toxav));
|
||||
sleeptime = qMin(sleeptime, CoreFile::corefileIterationInterval());
|
||||
toxTimer->start(sleeptime);
|
||||
}
|
||||
|
@ -754,8 +730,8 @@ void Core::removeGroup(int groupId, bool fake)
|
|||
|
||||
tox_del_groupchat(tox, groupId);
|
||||
|
||||
if (groupCalls[groupId].active)
|
||||
leaveGroupCall(groupId);
|
||||
if (av->groupCalls[groupId].active)
|
||||
av->leaveGroupCall(groupId);
|
||||
}
|
||||
|
||||
QString Core::getUsername() const
|
||||
|
@ -1078,11 +1054,6 @@ void Core::createGroup(uint8_t type)
|
|||
}
|
||||
}
|
||||
|
||||
bool Core::isGroupAvEnabled(int groupId)
|
||||
{
|
||||
return tox_group_get_type(tox, groupId) == TOX_GROUPCHAT_TYPE_AV;
|
||||
}
|
||||
|
||||
bool Core::isFriendOnline(uint32_t friendId) const
|
||||
{
|
||||
return tox_friend_get_connection_status(tox, friendId, nullptr) != TOX_CONNECTION_NONE;
|
||||
|
@ -1235,28 +1206,6 @@ void Core::setNospam(uint32_t nospam)
|
|||
tox_self_set_nospam(tox, nospam);
|
||||
}
|
||||
|
||||
void Core::resetCallSources()
|
||||
{
|
||||
for (ToxGroupCall& call : groupCalls)
|
||||
{
|
||||
for (ALuint source : call.alSources)
|
||||
alDeleteSources(1, &source);
|
||||
call.alSources.clear();
|
||||
}
|
||||
|
||||
for (ToxCall& call : calls)
|
||||
{
|
||||
if (call.active && call.alSource)
|
||||
{
|
||||
ALuint tmp = call.alSource;
|
||||
call.alSource = 0;
|
||||
alDeleteSources(1, &tmp);
|
||||
|
||||
alGenSources(1, &call.alSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::killTimers(bool onlyStop)
|
||||
{
|
||||
assert(QThread::currentThread() == coreThread);
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <tox/toxencryptsave.h>
|
||||
|
||||
#include "corestructs.h"
|
||||
#include "coreav.h"
|
||||
#include "coredefines.h"
|
||||
#include "toxid.h"
|
||||
|
||||
|
@ -38,11 +37,9 @@ template <typename T> class QList;
|
|||
class QTimer;
|
||||
class QString;
|
||||
class CString;
|
||||
class VideoSource;
|
||||
class VideoFrame;
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
class AudioFilterer;
|
||||
#endif
|
||||
struct ToxAV;
|
||||
class CoreAV;
|
||||
struct vpx_image;
|
||||
|
||||
class Core : public QObject
|
||||
{
|
||||
|
@ -50,6 +47,7 @@ class Core : public QObject
|
|||
public:
|
||||
explicit Core(QThread* coreThread, Profile& profile);
|
||||
static Core* getInstance(); ///< Returns the global widget's Core instance
|
||||
const CoreAV* getAv() const;
|
||||
~Core();
|
||||
|
||||
static const QString TOX_EXT;
|
||||
|
@ -88,13 +86,8 @@ public:
|
|||
static QByteArray decryptData(const QByteArray& data, const TOX_PASS_KEY &encryptionKey);
|
||||
static QByteArray decryptData(const QByteArray& data); ///< Uses the default profile's key
|
||||
|
||||
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
||||
|
||||
static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
|
||||
bool isReady(); ///< Most of the API shouldn't be used until Core is ready, call start() first
|
||||
|
||||
void resetCallSources(); ///< Forces to regenerate each call's audio sources
|
||||
|
||||
public slots:
|
||||
void start(); ///< Initializes the core, must be called before anything else
|
||||
void reset(); ///< Reinitialized the core. Must be called from the Core thread, with the GUI thread ready to process events.
|
||||
|
@ -132,27 +125,8 @@ public slots:
|
|||
void pauseResumeFileSend(uint32_t friendId, uint32_t fileNum);
|
||||
void pauseResumeFileRecv(uint32_t friendId, uint32_t fileNum);
|
||||
|
||||
void answerCall(int callId);
|
||||
void rejectCall(int callId);
|
||||
void hangupCall(int callId);
|
||||
void startCall(uint32_t friendId, bool video=false);
|
||||
void cancelCall(int callId, uint32_t friendId);
|
||||
|
||||
void micMuteToggle(int callId);
|
||||
void volMuteToggle(int callId);
|
||||
|
||||
void setNospam(uint32_t nospam);
|
||||
|
||||
bool isGroupAvEnabled(int groupId); ///< True for AV groups, false for text-only groups
|
||||
|
||||
static void joinGroupCall(int groupId); ///< Starts a call in an existing AV groupchat. Call from the GUI thread.
|
||||
static void leaveGroupCall(int groupId); ///< Will not leave the group, just stop the call. Call from the GUI thread.
|
||||
static void disableGroupCallMic(int groupId);
|
||||
static void disableGroupCallVol(int groupId);
|
||||
static void enableGroupCallMic(int groupId);
|
||||
static void enableGroupCallVol(int groupId);
|
||||
static bool isGroupCallMicEnabled(int groupId);
|
||||
static bool isGroupCallVolEnabled(int groupId);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
|
@ -256,28 +230,6 @@ private:
|
|||
const uint8_t* title, uint8_t len, void* _core);
|
||||
static void onReadReceiptCallback(Tox *tox, uint32_t friendId, uint32_t receipt, void *core);
|
||||
|
||||
static void onAvInvite(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvStart(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvCancel(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvReject(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvEnd(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvRinging(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvRequestTimeout(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvPeerTimeout(void* toxav, int32_t call_index, void* core);
|
||||
static void onAvMediaChange(void *toxav, int32_t call_index, void* core);
|
||||
|
||||
static void sendGroupCallAudio(int groupId, ToxAv* toxav);
|
||||
|
||||
static void prepareCall(uint32_t friendId, int callId, ToxAv *toxav, bool videoEnabled);
|
||||
static void cleanupCall(int callId);
|
||||
static void playCallAudio(void *toxav, int32_t callId, const int16_t *data,
|
||||
uint16_t samples, void *user_data); // Callback
|
||||
static void sendCallAudio(int callId, ToxAv* toxav);
|
||||
static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples,
|
||||
unsigned channels, int sampleRate);
|
||||
static void playCallVideo(void *toxav, int32_t callId, const vpx_image_t* img, void *user_data);
|
||||
static void sendCallVideo(int callId, ToxAv* toxav, std::shared_ptr<VideoFrame> frame);
|
||||
|
||||
bool checkConnection();
|
||||
|
||||
void checkEncryptedHistory();
|
||||
|
@ -293,24 +245,18 @@ private slots:
|
|||
|
||||
private:
|
||||
Tox* tox;
|
||||
ToxAv* toxav;
|
||||
ToxAV* toxav;
|
||||
CoreAV* av;
|
||||
QTimer *toxTimer;
|
||||
Profile& profile;
|
||||
static ToxCall calls[TOXAV_MAX_CALLS];
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
static AudioFilterer * filterer[TOXAV_MAX_CALLS];
|
||||
#endif
|
||||
static QHash<int, ToxGroupCall> groupCalls; // Maps group IDs to ToxGroupCalls
|
||||
QMutex messageSendMutex;
|
||||
bool ready;
|
||||
|
||||
static const int videobufsize;
|
||||
static uint8_t* videobuf;
|
||||
|
||||
static QThread *coreThread;
|
||||
|
||||
friend class Audio; ///< Audio can access our calls directly to reduce latency
|
||||
friend class CoreFile; ///< CoreFile can access tox* and emit our signals
|
||||
friend class CoreAV; ///< CoreAV accesses our toxav* for now
|
||||
};
|
||||
|
||||
#endif // CORE_HPP
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "coreav.h"
|
||||
#include "src/video/camerasource.h"
|
||||
#include "src/video/corevideosource.h"
|
||||
#include "src/video/videoframe.h"
|
||||
|
@ -31,14 +32,23 @@
|
|||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
ToxCall Core::calls[TOXAV_MAX_CALLS];
|
||||
QVector<ToxCall> CoreAV::calls;
|
||||
QHash<int, ToxGroupCall> CoreAV::groupCalls;
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
AudioFilterer * Core::filterer[TOXAV_MAX_CALLS] {nullptr};
|
||||
QVector<AudioFilterer*> CoreAV::filterer;
|
||||
#endif
|
||||
const int Core::videobufsize{TOXAV_MAX_VIDEO_WIDTH * TOXAV_MAX_VIDEO_HEIGHT * 4};
|
||||
uint8_t* Core::videobuf;
|
||||
|
||||
bool Core::anyActiveCalls()
|
||||
CoreAV::~CoreAV()
|
||||
{
|
||||
for (ToxCall call : calls)
|
||||
{
|
||||
if (!call.active)
|
||||
continue;
|
||||
hangupCall(call.callId);
|
||||
}
|
||||
}
|
||||
|
||||
bool CoreAV::anyActiveCalls()
|
||||
{
|
||||
for (auto& call : calls)
|
||||
{
|
||||
|
@ -48,26 +58,17 @@ bool Core::anyActiveCalls()
|
|||
return false;
|
||||
}
|
||||
|
||||
void Core::prepareCall(uint32_t friendId, int32_t callId, ToxAv* toxav, bool videoEnabled)
|
||||
void CoreAV::prepareCall(uint32_t friendId, int32_t callId, ToxAV* toxav, bool videoEnabled)
|
||||
{
|
||||
qDebug() << QString("preparing call %1").arg(callId);
|
||||
|
||||
if (!videobuf)
|
||||
videobuf = new uint8_t[videobufsize];
|
||||
|
||||
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].codecSettings = av_DefaultSettings;
|
||||
calls[callId].codecSettings.max_video_width = TOXAV_MAX_VIDEO_WIDTH;
|
||||
calls[callId].codecSettings.max_video_height = TOXAV_MAX_VIDEO_HEIGHT;
|
||||
calls[callId].videoEnabled = videoEnabled;
|
||||
int r = toxav_prepare_transmission(toxav, callId, videoEnabled);
|
||||
if (r < 0)
|
||||
qWarning() << QString("Error starting call %1: toxav_prepare_transmission failed with %2").arg(callId).arg(r);
|
||||
|
||||
// Audio
|
||||
Audio::getInstance().subscribeInput();
|
||||
|
@ -102,135 +103,35 @@ void Core::prepareCall(uint32_t friendId, int32_t callId, ToxAv* toxav, bool vid
|
|||
#endif
|
||||
}
|
||||
|
||||
void Core::onAvMediaChange(void* toxav, int32_t callId, void* core)
|
||||
void CoreAV::answerCall(int32_t callId)
|
||||
{
|
||||
int friendId;
|
||||
int cap = toxav_capability_supported((ToxAv*)toxav, callId,
|
||||
(ToxAvCapabilities)(av_VideoEncoding|av_VideoDecoding));
|
||||
if (!cap)
|
||||
goto fail;
|
||||
|
||||
friendId = toxav_get_peer_id((ToxAv*)toxav, callId, 0);
|
||||
if (friendId < 0)
|
||||
goto fail;
|
||||
|
||||
qDebug() << "Received media change from friend "<<friendId;
|
||||
|
||||
if (cap == (av_VideoEncoding|av_VideoDecoding)) // Video call
|
||||
{
|
||||
emit static_cast<Core*>(core)->avMediaChange(friendId, callId, true);
|
||||
calls[callId].videoSource = new CoreVideoSource;
|
||||
CameraSource& source = CameraSource::getInstance();
|
||||
source.subscribe();
|
||||
calls[callId].videoEnabled = true;
|
||||
}
|
||||
else // Audio call
|
||||
{
|
||||
emit static_cast<Core*>(core)->avMediaChange(friendId, callId, false);
|
||||
calls[callId].videoEnabled = false;
|
||||
CameraSource::getInstance().unsubscribe();
|
||||
calls[callId].videoSource->setDeleteOnClose(true);
|
||||
calls[callId].videoSource = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail: // Centralized error handling
|
||||
qWarning() << "Toxcore error while receiving media change on call "<<callId;
|
||||
return;
|
||||
}
|
||||
|
||||
void Core::answerCall(int32_t callId)
|
||||
{
|
||||
int friendId = toxav_get_peer_id(toxav, callId, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV answer peer ID";
|
||||
return;
|
||||
}
|
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings;
|
||||
int err = toxav_get_peer_csettings(toxav, callId, 0, transSettings);
|
||||
if (err != av_ErrorNone)
|
||||
{
|
||||
qWarning() << "answerCall: error getting call settings";
|
||||
delete transSettings;
|
||||
return;
|
||||
}
|
||||
|
||||
if (transSettings->call_type == av_TypeVideo)
|
||||
{
|
||||
qDebug() << QString("answering call %1 with video").arg(callId);
|
||||
toxav_answer(toxav, callId, transSettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << QString("answering call %1 without video").arg(callId);
|
||||
toxav_answer(toxav, callId, transSettings);
|
||||
}
|
||||
|
||||
delete transSettings;
|
||||
}
|
||||
|
||||
void Core::hangupCall(int32_t callId)
|
||||
void CoreAV::hangupCall(int32_t callId)
|
||||
{
|
||||
qDebug() << QString("hanging up call %1").arg(callId);
|
||||
toxav_hangup(toxav, callId);
|
||||
calls[callId].active = false;
|
||||
}
|
||||
|
||||
void Core::rejectCall(int32_t callId)
|
||||
void CoreAV::rejectCall(int32_t callId)
|
||||
{
|
||||
qDebug() << QString("rejecting call %1").arg(callId);
|
||||
calls[callId].active = false;
|
||||
toxav_reject(toxav, callId, nullptr);
|
||||
}
|
||||
|
||||
void Core::startCall(uint32_t friendId, bool video)
|
||||
void CoreAV::startCall(uint32_t friendId, bool video)
|
||||
{
|
||||
int32_t callId;
|
||||
ToxAvCSettings cSettings = av_DefaultSettings;
|
||||
cSettings.max_video_width = TOXAV_MAX_VIDEO_WIDTH;
|
||||
cSettings.max_video_height = TOXAV_MAX_VIDEO_HEIGHT;
|
||||
if (video)
|
||||
{
|
||||
qDebug() << QString("Starting new call with %1 with video").arg(friendId);
|
||||
cSettings.call_type = av_TypeVideo;
|
||||
if (toxav_call(toxav, &callId, friendId, &cSettings, TOXAV_RINGING_TIME) == 0)
|
||||
{
|
||||
calls[callId].videoEnabled=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << QString("Failed to start new video call with %1").arg(friendId);
|
||||
emit avCallFailed(friendId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << QString("Starting new call with %1 without video").arg(friendId);
|
||||
cSettings.call_type = av_TypeAudio;
|
||||
if (toxav_call(toxav, &callId, friendId, &cSettings, TOXAV_RINGING_TIME) == 0)
|
||||
{
|
||||
calls[callId].videoEnabled=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << QString("Failed to start new audio call with %1").arg(friendId);
|
||||
emit avCallFailed(friendId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Core::cancelCall(int32_t callId, uint32_t friendId)
|
||||
void CoreAV::cancelCall(int32_t callId, uint32_t friendId)
|
||||
{
|
||||
qDebug() << QString("Cancelling call with %1").arg(friendId);
|
||||
calls[callId].active = false;
|
||||
toxav_cancel(toxav, callId, friendId, nullptr);
|
||||
}
|
||||
|
||||
void Core::cleanupCall(int32_t callId)
|
||||
void CoreAV::cleanupCall(int32_t callId)
|
||||
{
|
||||
assert(calls[callId].active);
|
||||
qDebug() << QString("cleaning up call %1").arg(callId);
|
||||
|
@ -249,16 +150,10 @@ void Core::cleanupCall(int32_t callId)
|
|||
}
|
||||
|
||||
Audio::getInstance().unsubscribeInput();
|
||||
toxav_kill_transmission(Core::getInstance()->toxav, callId);
|
||||
|
||||
if (!anyActiveCalls())
|
||||
{
|
||||
delete[] videobuf;
|
||||
videobuf = nullptr;
|
||||
}
|
||||
//toxav_kill_transmission(Core::getInstance()->toxav, callId);
|
||||
}
|
||||
|
||||
void Core::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);
|
||||
|
||||
|
@ -268,12 +163,12 @@ void Core::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint1
|
|||
if (!calls[callId].alSource)
|
||||
alGenSources(1, &calls[callId].alSource);
|
||||
|
||||
ToxAvCSettings dest;
|
||||
if (toxav_get_peer_csettings((ToxAv*)toxav, callId, 0, &dest) == 0)
|
||||
playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate);
|
||||
//ToxAvCSettings dest;
|
||||
//if (toxav_get_peer_csettings((ToxAV*)toxav, callId, 0, &dest) == 0)
|
||||
// playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate);
|
||||
}
|
||||
|
||||
void Core::sendCallAudio(int32_t callId, ToxAv* toxav)
|
||||
void CoreAV::sendCallAudio(int32_t callId, ToxAV* toxav)
|
||||
{
|
||||
if (!calls[callId].active)
|
||||
return;
|
||||
|
@ -284,6 +179,7 @@ void Core::sendCallAudio(int32_t callId, ToxAv* toxav)
|
|||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
const int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000 * av_DefaultSettings.audio_channels;
|
||||
const int bufsize = framesize * 2 * av_DefaultSettings.audio_channels;
|
||||
uint8_t buf[bufsize];
|
||||
|
@ -322,10 +218,11 @@ void Core::sendCallAudio(int32_t callId, ToxAv* toxav)
|
|||
if ((r = toxav_send_audio(toxav, callId, dest, r)) < 0)
|
||||
qDebug() << "toxav_send_audio error";
|
||||
}
|
||||
#endif
|
||||
calls[callId].sendAudioTimer->start();
|
||||
}
|
||||
|
||||
void Core::playCallVideo(void*, int32_t callId, const vpx_image_t* img, void *user_data)
|
||||
void CoreAV::playCallVideo(void*, int32_t callId, const vpx_image *img, void *user_data)
|
||||
{
|
||||
Q_UNUSED(user_data);
|
||||
|
||||
|
@ -335,7 +232,7 @@ void Core::playCallVideo(void*, int32_t callId, const vpx_image_t* img, void *us
|
|||
calls[callId].videoSource->pushFrame(img);
|
||||
}
|
||||
|
||||
void Core::sendCallVideo(int32_t callId, ToxAv* toxav, std::shared_ptr<VideoFrame> vframe)
|
||||
void CoreAV::sendCallVideo(int32_t callId, ToxAV* toxav, std::shared_ptr<VideoFrame> vframe)
|
||||
{
|
||||
if (!calls[callId].active || !calls[callId].videoEnabled)
|
||||
return;
|
||||
|
@ -349,6 +246,7 @@ void Core::sendCallVideo(int32_t callId, ToxAv* toxav, std::shared_ptr<VideoFram
|
|||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int result;
|
||||
if ((result = toxav_prepare_video_frame(toxav, callId, videobuf, videobufsize, frame)) < 0)
|
||||
{
|
||||
|
@ -359,213 +257,25 @@ void Core::sendCallVideo(int32_t callId, ToxAv* toxav, std::shared_ptr<VideoFram
|
|||
|
||||
if ((result = toxav_send_video(toxav, callId, (uint8_t*)videobuf, result)) < 0)
|
||||
qDebug() << QString("toxav_send_video error: %1").arg(result);
|
||||
#endif
|
||||
|
||||
delete frame;
|
||||
}
|
||||
|
||||
void Core::micMuteToggle(int32_t callId)
|
||||
void CoreAV::micMuteToggle(int32_t callId)
|
||||
{
|
||||
if (calls[callId].active)
|
||||
calls[callId].muteMic = !calls[callId].muteMic;
|
||||
}
|
||||
|
||||
void Core::volMuteToggle(int32_t callId)
|
||||
void CoreAV::volMuteToggle(int32_t callId)
|
||||
{
|
||||
if (calls[callId].active)
|
||||
calls[callId].muteVol = !calls[callId].muteVol;
|
||||
}
|
||||
|
||||
void Core::onAvCancel(void* _toxav, int32_t callId, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, callId, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV cancel";
|
||||
return;
|
||||
}
|
||||
qDebug() << QString("AV cancel from %1").arg(friendId);
|
||||
|
||||
calls[callId].active = false;
|
||||
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
if (filterer[callId])
|
||||
{
|
||||
filterer[callId]->closeFilter();
|
||||
delete filterer[callId];
|
||||
filterer[callId] = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
emit static_cast<Core*>(core)->avCancel(friendId, callId);
|
||||
}
|
||||
|
||||
void Core::onAvReject(void* _toxav, int32_t callId, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
int friendId = toxav_get_peer_id(toxav, callId, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV reject";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << QString("AV reject from %1").arg(friendId);
|
||||
|
||||
emit static_cast<Core*>(core)->avRejected(friendId, callId);
|
||||
}
|
||||
|
||||
void Core::onAvEnd(void* _toxav, int32_t call_index, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV end";
|
||||
return;
|
||||
}
|
||||
qDebug() << QString("AV end from %1").arg(friendId);
|
||||
|
||||
emit static_cast<Core*>(core)->avEnd(friendId, call_index);
|
||||
|
||||
if (calls[call_index].active)
|
||||
cleanupCall(call_index);
|
||||
}
|
||||
|
||||
void Core::onAvRinging(void* _toxav, int32_t call_index, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV ringing";
|
||||
return;
|
||||
}
|
||||
|
||||
if (calls[call_index].videoEnabled)
|
||||
{
|
||||
qDebug() << QString("AV ringing with %1 with video").arg(friendId);
|
||||
emit static_cast<Core*>(core)->avRinging(friendId, call_index, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << QString("AV ringing with %1 without video").arg(friendId);
|
||||
emit static_cast<Core*>(core)->avRinging(friendId, call_index, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::onAvRequestTimeout(void* _toxav, int32_t call_index, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV request timeout";
|
||||
return;
|
||||
}
|
||||
qDebug() << QString("AV request timeout with %1").arg(friendId);
|
||||
|
||||
emit static_cast<Core*>(core)->avRequestTimeout(friendId, call_index);
|
||||
|
||||
if (calls[call_index].active)
|
||||
cleanupCall(call_index);
|
||||
}
|
||||
|
||||
void Core::onAvPeerTimeout(void* _toxav, int32_t call_index, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV peer timeout";
|
||||
return;
|
||||
}
|
||||
qDebug() << QString("AV peer timeout with %1").arg(friendId);
|
||||
|
||||
emit static_cast<Core*>(core)->avPeerTimeout(friendId, call_index);
|
||||
|
||||
if (calls[call_index].active)
|
||||
cleanupCall(call_index);
|
||||
}
|
||||
|
||||
|
||||
void Core::onAvInvite(void* _toxav, int32_t call_index, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV invite";
|
||||
return;
|
||||
}
|
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings;
|
||||
int err = toxav_get_peer_csettings(toxav, call_index, 0, transSettings);
|
||||
if (err != av_ErrorNone)
|
||||
{
|
||||
qWarning() << "onAvInvite: error getting call type";
|
||||
delete transSettings;
|
||||
return;
|
||||
}
|
||||
|
||||
if (transSettings->call_type == av_TypeVideo)
|
||||
{
|
||||
qDebug() << QString("AV invite from %1 with video").arg(friendId);
|
||||
emit static_cast<Core*>(core)->avInvite(friendId, call_index, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << QString("AV invite from %1 without video").arg(friendId);
|
||||
emit static_cast<Core*>(core)->avInvite(friendId, call_index, false);
|
||||
}
|
||||
|
||||
delete transSettings;
|
||||
}
|
||||
|
||||
void Core::onAvStart(void* _toxav, int32_t call_index, void* core)
|
||||
{
|
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav);
|
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0);
|
||||
if (friendId < 0)
|
||||
{
|
||||
qWarning() << "Received invalid AV start";
|
||||
return;
|
||||
}
|
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings;
|
||||
int err = toxav_get_peer_csettings(toxav, call_index, 0, transSettings);
|
||||
if (err != av_ErrorNone)
|
||||
{
|
||||
qWarning() << "onAvStart: error getting call type";
|
||||
delete transSettings;
|
||||
return;
|
||||
}
|
||||
|
||||
if (transSettings->call_type == av_TypeVideo)
|
||||
{
|
||||
qDebug() << QString("AV start from %1 with video").arg(friendId);
|
||||
prepareCall(friendId, call_index, toxav, true);
|
||||
emit static_cast<Core*>(core)->avStart(friendId, call_index, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << QString("AV start from %1 without video").arg(friendId);
|
||||
prepareCall(friendId, call_index, toxav, false);
|
||||
emit static_cast<Core*>(core)->avStart(friendId, call_index, false);
|
||||
}
|
||||
|
||||
delete transSettings;
|
||||
}
|
||||
|
||||
// This function's logic was shamelessly stolen from uTox
|
||||
void Core::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate)
|
||||
void CoreAV::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate)
|
||||
{
|
||||
if (!channels || channels > 2)
|
||||
{
|
||||
|
@ -610,12 +320,12 @@ void Core::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, un
|
|||
}
|
||||
}
|
||||
|
||||
VideoSource *Core::getVideoSourceFromCall(int callNumber)
|
||||
VideoSource *CoreAV::getVideoSourceFromCall(int callNumber)
|
||||
{
|
||||
return calls[callNumber].videoSource;
|
||||
}
|
||||
|
||||
void Core::joinGroupCall(int groupId)
|
||||
void CoreAV::joinGroupCall(int groupId)
|
||||
{
|
||||
qDebug() << QString("Joining group call %1").arg(groupId);
|
||||
groupCalls[groupId].groupId = groupId;
|
||||
|
@ -623,16 +333,13 @@ void Core::joinGroupCall(int groupId)
|
|||
groupCalls[groupId].muteVol = false;
|
||||
// the following three lines are also now redundant from startCall, but are
|
||||
// necessary there for outbound and here for inbound
|
||||
groupCalls[groupId].codecSettings = av_DefaultSettings;
|
||||
groupCalls[groupId].codecSettings.max_video_width = TOXAV_MAX_VIDEO_WIDTH;
|
||||
groupCalls[groupId].codecSettings.max_video_height = TOXAV_MAX_VIDEO_HEIGHT;
|
||||
|
||||
// Audio
|
||||
Audio::getInstance().subscribeInput();
|
||||
|
||||
// Go
|
||||
Core* core = Core::getInstance();
|
||||
ToxAv* toxav = core->toxav;
|
||||
ToxAV* toxav = core->toxav;
|
||||
|
||||
groupCalls[groupId].sendAudioTimer = new QTimer();
|
||||
groupCalls[groupId].active = true;
|
||||
|
@ -642,7 +349,7 @@ void Core::joinGroupCall(int groupId)
|
|||
groupCalls[groupId].sendAudioTimer->start();
|
||||
}
|
||||
|
||||
void Core::leaveGroupCall(int groupId)
|
||||
void CoreAV::leaveGroupCall(int groupId)
|
||||
{
|
||||
qDebug() << QString("Leaving group call %1").arg(groupId);
|
||||
groupCalls[groupId].active = false;
|
||||
|
@ -655,7 +362,7 @@ void Core::leaveGroupCall(int groupId)
|
|||
delete groupCalls[groupId].sendAudioTimer;
|
||||
}
|
||||
|
||||
void Core::sendGroupCallAudio(int groupId, ToxAv* toxav)
|
||||
void CoreAV::sendGroupCallAudio(int groupId, ToxAV *toxav)
|
||||
{
|
||||
if (!groupCalls[groupId].active)
|
||||
return;
|
||||
|
@ -666,6 +373,7 @@ void Core::sendGroupCallAudio(int groupId, ToxAv* toxav)
|
|||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
const int framesize = (groupCalls[groupId].codecSettings.audio_frame_duration * groupCalls[groupId].codecSettings.audio_sample_rate) / 1000 * av_DefaultSettings.audio_channels;
|
||||
const int bufsize = framesize * 2 * av_DefaultSettings.audio_channels;
|
||||
uint8_t buf[bufsize];
|
||||
|
@ -680,35 +388,63 @@ void Core::sendGroupCallAudio(int groupId, ToxAv* toxav)
|
|||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
groupCalls[groupId].sendAudioTimer->start();
|
||||
}
|
||||
|
||||
void Core::disableGroupCallMic(int groupId)
|
||||
void CoreAV::disableGroupCallMic(int groupId)
|
||||
{
|
||||
groupCalls[groupId].muteMic = true;
|
||||
}
|
||||
|
||||
void Core::disableGroupCallVol(int groupId)
|
||||
void CoreAV::disableGroupCallVol(int groupId)
|
||||
{
|
||||
groupCalls[groupId].muteVol = true;
|
||||
}
|
||||
|
||||
void Core::enableGroupCallMic(int groupId)
|
||||
void CoreAV::enableGroupCallMic(int groupId)
|
||||
{
|
||||
groupCalls[groupId].muteMic = false;
|
||||
}
|
||||
|
||||
void Core::enableGroupCallVol(int groupId)
|
||||
void CoreAV::enableGroupCallVol(int groupId)
|
||||
{
|
||||
groupCalls[groupId].muteVol = false;
|
||||
}
|
||||
|
||||
bool Core::isGroupCallMicEnabled(int groupId)
|
||||
bool CoreAV::isGroupCallMicEnabled(int groupId)
|
||||
{
|
||||
return !groupCalls[groupId].muteMic;
|
||||
}
|
||||
|
||||
bool Core::isGroupCallVolEnabled(int groupId)
|
||||
bool CoreAV::isGroupCallVolEnabled(int groupId)
|
||||
{
|
||||
return !groupCalls[groupId].muteVol;
|
||||
}
|
||||
|
||||
bool CoreAV::isGroupAvEnabled(int groupId)
|
||||
{
|
||||
return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV;
|
||||
}
|
||||
|
||||
void CoreAV::resetCallSources()
|
||||
{
|
||||
for (ToxGroupCall& call : groupCalls)
|
||||
{
|
||||
for (ALuint source : call.alSources)
|
||||
alDeleteSources(1, &source);
|
||||
call.alSources.clear();
|
||||
}
|
||||
|
||||
for (ToxCall& call : calls)
|
||||
{
|
||||
if (call.active && call.alSource)
|
||||
{
|
||||
ALuint tmp = call.alSource;
|
||||
call.alSource = 0;
|
||||
alDeleteSources(1, &tmp);
|
||||
|
||||
alGenSources(1, &call.alSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#define COREAV_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QThread>
|
||||
#include <memory>
|
||||
#include <tox/toxav.h>
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
|
@ -32,13 +34,19 @@
|
|||
#include <AL/alc.h>
|
||||
#endif
|
||||
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
class AudioFilterer;
|
||||
#endif
|
||||
|
||||
class QTimer;
|
||||
class CoreVideoSource;
|
||||
class CameraSource;
|
||||
class VideoSource;
|
||||
class VideoFrame;
|
||||
struct vpx_image;
|
||||
|
||||
struct ToxCall
|
||||
{
|
||||
ToxAvCSettings codecSettings;
|
||||
QTimer *sendAudioTimer;
|
||||
int32_t callId;
|
||||
uint32_t friendId;
|
||||
|
@ -52,7 +60,6 @@ struct ToxCall
|
|||
|
||||
struct ToxGroupCall
|
||||
{
|
||||
ToxAvCSettings codecSettings;
|
||||
QTimer *sendAudioTimer;
|
||||
int groupId;
|
||||
bool active = false;
|
||||
|
@ -61,4 +68,58 @@ struct ToxGroupCall
|
|||
QHash<int, ALuint> alSources;
|
||||
};
|
||||
|
||||
class CoreAV : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CoreAV() = default;
|
||||
~CoreAV();
|
||||
|
||||
static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
|
||||
static void prepareCall(uint32_t friendId, int callId, ToxAV *toxav, bool videoEnabled);
|
||||
static void cleanupCall(int callId);
|
||||
static void playCallAudio(void *toxav, int32_t callId, const int16_t *data,
|
||||
uint16_t samples, void *user_data); // Callback
|
||||
static void sendCallAudio(int callId, ToxAV* toxav);
|
||||
static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples,
|
||||
unsigned channels, int sampleRate);
|
||||
static void playCallVideo(void *toxav, int32_t callId, const vpx_image* img, void *user_data);
|
||||
static void sendCallVideo(int callId, ToxAV* toxav, std::shared_ptr<VideoFrame> frame);
|
||||
static void sendGroupCallAudio(int groupId, ToxAV* toxav);
|
||||
|
||||
static VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
||||
static void resetCallSources(); ///< Forces to regenerate each call's audio sources
|
||||
|
||||
static void joinGroupCall(int groupId); ///< Starts a call in an existing AV groupchat. Call from the GUI thread.
|
||||
static void leaveGroupCall(int groupId); ///< Will not leave the group, just stop the call. Call from the GUI thread.
|
||||
static void disableGroupCallMic(int groupId);
|
||||
static void disableGroupCallVol(int groupId);
|
||||
static void enableGroupCallMic(int groupId);
|
||||
static void enableGroupCallVol(int groupId);
|
||||
static bool isGroupCallMicEnabled(int groupId);
|
||||
static bool isGroupCallVolEnabled(int groupId);
|
||||
static bool isGroupAvEnabled(int groupId); ///< True for AV groups, false for text-only groups
|
||||
|
||||
public slots:
|
||||
static void answerCall(int callId);
|
||||
static void rejectCall(int callId);
|
||||
static void hangupCall(int callId);
|
||||
static void startCall(uint32_t friendId, bool video=false);
|
||||
static void cancelCall(int callId, uint32_t friendId);
|
||||
|
||||
static void micMuteToggle(int callId);
|
||||
static void volMuteToggle(int callId);
|
||||
|
||||
private:
|
||||
static QVector<ToxCall> calls;
|
||||
#ifdef QTOX_FILTER_AUDIO
|
||||
static QVector<AudioFilterer*> filterer;
|
||||
#endif
|
||||
static QHash<int, ToxGroupCall> groupCalls; // Maps group IDs to ToxGroupCalls
|
||||
|
||||
friend class Audio;
|
||||
friend class Core;
|
||||
};
|
||||
|
||||
#endif // COREAV_H
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#ifndef COREDEFINES_H
|
||||
#define COREDEFINES_H
|
||||
|
||||
#define TOXAV_MAX_CALLS 16
|
||||
#define TOXAV_RINGING_TIME 45
|
||||
|
||||
// TODO: Put that in the settings
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <QFile>
|
||||
#include <QApplication>
|
||||
#include <cassert>
|
||||
#include <vpx/vpx_image.h>
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <src/widget/androidgui.h>
|
||||
|
|
|
@ -35,8 +35,8 @@ public:
|
|||
virtual void unsubscribe() override;
|
||||
|
||||
private:
|
||||
// Only Core should create a CoreVideoSource since
|
||||
// only Core can push images to it
|
||||
// Only CoreAV should create a CoreVideoSource since
|
||||
// only CoreAV can push images to it
|
||||
CoreVideoSource();
|
||||
|
||||
/// Makes a copy of the vpx_image_t and emits it as a new VideoFrame
|
||||
|
@ -49,7 +49,7 @@ private:
|
|||
std::atomic_bool deleteOnClose; ///< If true, self-delete after the last suscriber is gone
|
||||
std::atomic_bool biglock; ///< Fast lock
|
||||
|
||||
friend class Core;
|
||||
friend class CoreAV;
|
||||
};
|
||||
|
||||
#endif // COREVIDEOSOURCE_H
|
||||
|
|
|
@ -33,6 +33,7 @@ class VideoSource : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~VideoSource() = default;
|
||||
/// If subscribe sucessfully opens the source, it will start emitting frameAvailable signals
|
||||
virtual bool subscribe() = 0;
|
||||
/// Stop emitting frameAvailable signals, and free associated resources if necessary
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <cassert>
|
||||
#include "chatform.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/core/coreav.h"
|
||||
#include "src/friend.h"
|
||||
#include "src/persistence/historykeeper.h"
|
||||
#include "src/widget/style.h"
|
||||
|
@ -756,7 +757,7 @@ GenericNetCamView *ChatForm::createNetcam()
|
|||
{
|
||||
qDebug() << "creating netcam";
|
||||
NetCamView* view = new NetCamView(f->getFriendID(), this);
|
||||
view->show(Core::getInstance()->getVideoSourceFromCall(callId), f->getDisplayedName());
|
||||
view->show(CoreAV::getVideoSourceFromCall(callId), f->getDisplayedName());
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "src/widget/tool/croppinglabel.h"
|
||||
#include "src/widget/maskablepixmapwidget.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/core/coreav.h"
|
||||
#include "src/widget/style.h"
|
||||
#include "src/persistence/historykeeper.h"
|
||||
#include "src/widget/flowlayout.h"
|
||||
|
@ -282,13 +283,13 @@ void GroupChatForm::onMicMuteToggle()
|
|||
{
|
||||
if (micButton->objectName() == "red")
|
||||
{
|
||||
Core::getInstance()->enableGroupCallMic(group->getGroupId());
|
||||
CoreAV::enableGroupCallMic(group->getGroupId());
|
||||
micButton->setObjectName("green");
|
||||
micButton->setToolTip(tr("Mute microphone"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Core::getInstance()->disableGroupCallMic(group->getGroupId());
|
||||
CoreAV::disableGroupCallMic(group->getGroupId());
|
||||
micButton->setObjectName("red");
|
||||
micButton->setToolTip(tr("Unmute microphone"));
|
||||
}
|
||||
|
@ -303,13 +304,13 @@ void GroupChatForm::onVolMuteToggle()
|
|||
{
|
||||
if (volButton->objectName() == "red")
|
||||
{
|
||||
Core::getInstance()->enableGroupCallVol(group->getGroupId());
|
||||
CoreAV::enableGroupCallVol(group->getGroupId());
|
||||
volButton->setObjectName("green");
|
||||
volButton->setToolTip(tr("Mute call"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Core::getInstance()->disableGroupCallVol(group->getGroupId());
|
||||
CoreAV::disableGroupCallVol(group->getGroupId());
|
||||
volButton->setObjectName("red");
|
||||
volButton->setToolTip(tr("Unmute call"));
|
||||
}
|
||||
|
@ -322,7 +323,7 @@ void GroupChatForm::onCallClicked()
|
|||
{
|
||||
if (!inCall)
|
||||
{
|
||||
Core::getInstance()->joinGroupCall(group->getGroupId());
|
||||
CoreAV::joinGroupCall(group->getGroupId());
|
||||
audioInputFlag = true;
|
||||
audioOutputFlag = true;
|
||||
callButton->setObjectName("red");
|
||||
|
@ -339,7 +340,7 @@ void GroupChatForm::onCallClicked()
|
|||
}
|
||||
else
|
||||
{
|
||||
Core::getInstance()->leaveGroupCall(group->getGroupId());
|
||||
CoreAV::leaveGroupCall(group->getGroupId());
|
||||
audioInputFlag = false;
|
||||
audioOutputFlag = false;
|
||||
callButton->setObjectName("green");
|
||||
|
@ -375,10 +376,9 @@ void GroupChatForm::keyPressEvent(QKeyEvent* ev)
|
|||
// Push to talk (CTRL+P)
|
||||
if (ev->key() == Qt::Key_P && (ev->modifiers() & Qt::ControlModifier) && inCall)
|
||||
{
|
||||
Core* core = Core::getInstance();
|
||||
if (!core->isGroupCallMicEnabled(group->getGroupId()))
|
||||
if (!CoreAV::isGroupCallMicEnabled(group->getGroupId()))
|
||||
{
|
||||
core->enableGroupCallMic(group->getGroupId());
|
||||
CoreAV::enableGroupCallMic(group->getGroupId());
|
||||
micButton->setObjectName("green");
|
||||
micButton->style()->polish(micButton);
|
||||
Style::repolish(micButton);
|
||||
|
@ -394,10 +394,9 @@ void GroupChatForm::keyReleaseEvent(QKeyEvent* ev)
|
|||
// Push to talk (CTRL+P)
|
||||
if (ev->key() == Qt::Key_P && (ev->modifiers() & Qt::ControlModifier) && inCall)
|
||||
{
|
||||
Core* core = Core::getInstance();
|
||||
if (core->isGroupCallMicEnabled(group->getGroupId()))
|
||||
if (CoreAV::isGroupCallMicEnabled(group->getGroupId()))
|
||||
{
|
||||
core->disableGroupCallMic(group->getGroupId());
|
||||
CoreAV::disableGroupCallMic(group->getGroupId());
|
||||
micButton->setObjectName("red");
|
||||
micButton->style()->polish(micButton);
|
||||
Style::repolish(micButton);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "src/persistence/settings.h"
|
||||
#include "src/persistence/smileypack.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/core/coreav.h"
|
||||
#include "src/widget/style.h"
|
||||
#include "src/nexus.h"
|
||||
#include "src/persistence/profile.h"
|
||||
|
@ -358,7 +359,7 @@ void GeneralForm::onUseProxyUpdated()
|
|||
|
||||
void GeneralForm::onReconnectClicked()
|
||||
{
|
||||
if (Core::getInstance()->anyActiveCalls())
|
||||
if (CoreAV::anyActiveCalls())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Call active", "popup title"),
|
||||
tr("You can't disconnect while a call is active!", "popup text"));
|
||||
|
|
|
@ -25,7 +25,7 @@ class GenericForm : public QWidget
|
|||
Q_OBJECT
|
||||
public:
|
||||
GenericForm(const QPixmap &icon) : formIcon(icon) {;}
|
||||
~GenericForm() {}
|
||||
virtual ~GenericForm() {}
|
||||
|
||||
virtual QString getFormName() = 0;
|
||||
QPixmap getFormIcon() {return formIcon;}
|
||||
|
|
|
@ -27,6 +27,7 @@ class AdjustingScrollArea : public QScrollArea
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit AdjustingScrollArea(QWidget *parent = 0);
|
||||
virtual ~AdjustingScrollArea() = default;
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *ev) override;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "contentlayout.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/core/coreav.h"
|
||||
#include "src/persistence/settings.h"
|
||||
#include "contentdialog.h"
|
||||
#include "src/friend.h"
|
||||
|
@ -890,13 +891,13 @@ void Widget::addFriend(int friendId, const QString &userId)
|
|||
connect(newfriend->getChatForm(), &GenericChatForm::sendMessage, core, &Core::sendMessage);
|
||||
connect(newfriend->getChatForm(), &GenericChatForm::sendAction, core, &Core::sendAction);
|
||||
connect(newfriend->getChatForm(), &ChatForm::sendFile, core, &Core::sendFile);
|
||||
connect(newfriend->getChatForm(), &ChatForm::answerCall, core, &Core::answerCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::hangupCall, core, &Core::hangupCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::rejectCall, core, &Core::rejectCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::startCall, core, &Core::startCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::cancelCall, core, &Core::cancelCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::micMuteToggle, core, &Core::micMuteToggle);
|
||||
connect(newfriend->getChatForm(), &ChatForm::volMuteToggle, core, &Core::volMuteToggle);
|
||||
connect(newfriend->getChatForm(), &ChatForm::answerCall, core->getAv(), &CoreAV::answerCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::hangupCall, core->getAv(), &CoreAV::hangupCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::rejectCall, core->getAv(), &CoreAV::rejectCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::startCall, core->getAv(), &CoreAV::startCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::cancelCall, core->getAv(), &CoreAV::cancelCall);
|
||||
connect(newfriend->getChatForm(), &ChatForm::micMuteToggle, core->getAv(), &CoreAV::micMuteToggle);
|
||||
connect(newfriend->getChatForm(), &ChatForm::volMuteToggle, core->getAv(), &CoreAV::volMuteToggle);
|
||||
connect(newfriend->getChatForm(), &ChatForm::aliasChanged, newfriend->getFriendWidget(), &FriendWidget::setAlias);
|
||||
connect(core, &Core::fileReceiveRequested, newfriend->getChatForm(), &ChatForm::onFileRecvRequest);
|
||||
connect(core, &Core::avInvite, newfriend->getChatForm(), &ChatForm::onAvInvite);
|
||||
|
@ -1588,7 +1589,7 @@ Group *Widget::createGroup(int groupId)
|
|||
Core* core = Nexus::getCore();
|
||||
|
||||
QString groupName = QString("Groupchat #%1").arg(groupId);
|
||||
Group* newgroup = GroupList::addGroup(groupId, groupName, core->isGroupAvEnabled(groupId));
|
||||
Group* newgroup = GroupList::addGroup(groupId, groupName, CoreAV::isGroupAvEnabled(groupId));
|
||||
|
||||
contactListWidget->addGroupWidget(newgroup->getGroupWidget());
|
||||
newgroup->getGroupWidget()->updateStatusLight();
|
||||
|
|
Loading…
Reference in New Issue
Block a user