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

docs(core): Change comment style

This commit is contained in:
Diadlo 2016-07-27 01:21:22 +03:00
parent 1c547fc73f
commit 2696a9265a
No known key found for this signature in database
GPG Key ID: 5AF9F2E29107C727
20 changed files with 497 additions and 147 deletions

View File

@ -104,6 +104,9 @@ Core::~Core()
deadifyTox();
}
/**
@brief Returns the global widget's Core instance
*/
Core* Core::getInstance()
{
return Nexus::getCore();
@ -217,6 +220,9 @@ void Core::makeTox(QByteArray savedata)
}
}
/**
@brief Initializes the core, must be called before anything else
*/
void Core::start()
{
bool isNewProfile = profile.isNewProfile();
@ -329,6 +335,9 @@ void Core::start()
*/
#define CORE_DISCONNECT_TOLERANCE 30
/**
@brief Processes toxcore events and ensure we stay connected, called by its own timer
*/
void Core::process()
{
if (!isReady())
@ -383,6 +392,9 @@ bool Core::checkConnection()
return isConnected;
}
/**
@brief Connects us to the Tox network
*/
void Core::bootstrapDht()
{
const Settings& s = Settings::getInstance();
@ -720,6 +732,9 @@ void Core::removeGroup(int groupId, bool fake)
av->leaveGroupCall(groupId);
}
/**
@brief Returns our username, or an empty string on failure
*/
QString Core::getUsername() const
{
QString sname;
@ -769,6 +784,9 @@ void Core::setAvatar(const QByteArray& data)
AvatarBroadcaster::enableAutoBroadcast();
}
/**
@brief Returns our Tox ID
*/
ToxId Core::getSelfId() const
{
uint8_t friendAddress[TOX_ADDRESS_SIZE] = {0};
@ -776,6 +794,9 @@ ToxId Core::getSelfId() const
return ToxId(CFriendAddress::toString(friendAddress));
}
/**
@brief Returns our public and private keys
*/
QPair<QByteArray, QByteArray> Core::getKeypair() const
{
QPair<QByteArray, QByteArray> keypair;
@ -790,6 +811,9 @@ QPair<QByteArray, QByteArray> Core::getKeypair() const
return keypair;
}
/**
@brief Returns our status message, or an empty string on failure
*/
QString Core::getStatusMessage() const
{
QString sname;
@ -803,6 +827,9 @@ QString Core::getStatusMessage() const
return sname;
}
/**
@brief Returns our user status
*/
Status Core::getStatus() const
{
return (Status)tox_self_get_status(tox);
@ -867,6 +894,9 @@ QString Core::sanitize(QString name)
return name;
}
/**
@brief Returns the unencrypted tox save data
*/
QByteArray Core::getToxSaveData()
{
uint32_t fileSize = tox_get_savedata_size(tox);
@ -925,6 +955,9 @@ void Core::checkLastOnline(uint32_t friendId) {
emit friendLastSeenChanged(friendId, QDateTime::fromTime_t(lastOnline));
}
/**
@brief Returns the list of friendIds in our friendlist, an empty list on error
*/
QVector<uint32_t> Core::getFriendList() const
{
QVector<uint32_t> friends;
@ -933,11 +966,17 @@ QVector<uint32_t> Core::getFriendList() const
return friends;
}
/**
@brief Return the number of peers in the group chat on success, or -1 on failure
*/
int Core::getGroupNumberPeers(int groupId) const
{
return tox_group_number_peers(tox, groupId);
}
/**
@brief Get the name of a peer of a group
*/
QString Core::getGroupPeerName(int groupId, int peerId) const
{
QString name;
@ -952,6 +991,9 @@ QString Core::getGroupPeerName(int groupId, int peerId) const
return name;
}
/**
@brief Get the public key of a peer of a group
*/
ToxId Core::getGroupPeerToxId(int groupId, int peerId) const
{
ToxId peerToxId;
@ -968,6 +1010,9 @@ ToxId Core::getGroupPeerToxId(int groupId, int peerId) const
return peerToxId;
}
/**
@brief Get the names of the peers of a group
*/
QList<QString> Core::getGroupPeerNames(int groupId) const
{
QList<QString> names;
@ -999,6 +1044,9 @@ QList<QString> Core::getGroupPeerNames(int groupId) const
return names;
}
/**
@brief Accept a groupchat invite
*/
int Core::joinGroupchat(int32_t friendnumber, uint8_t type, const uint8_t* friend_group_public_key,uint16_t length) const
{
if (type == TOX_GROUPCHAT_TYPE_TEXT)
@ -1020,6 +1068,9 @@ int Core::joinGroupchat(int32_t friendnumber, uint8_t type, const uint8_t* frien
}
}
/**
@brief Quit a groupchat
*/
void Core::quitGroupChat(int groupId) const
{
tox_del_groupchat(tox, groupId);
@ -1052,11 +1103,17 @@ int Core::createGroup(uint8_t type)
}
}
/**
@brief Checks if a friend is online. Unknown friends are considered offline.
*/
bool Core::isFriendOnline(uint32_t friendId) const
{
return tox_friend_get_connection_status(tox, friendId, nullptr) != TOX_CONNECTION_NONE;
}
/**
@brief Checks if we have a friend by address
*/
bool Core::hasFriendWithAddress(const QString &addr) const
{
// Valid length check
@ -1069,6 +1126,9 @@ bool Core::hasFriendWithAddress(const QString &addr) const
return hasFriendWithPublicKey(pubkey);
}
/**
@brief Checks if we have a friend by public key
*/
bool Core::hasFriendWithPublicKey(const QString &pubkey) const
{
// Valid length check
@ -1100,6 +1160,9 @@ bool Core::hasFriendWithPublicKey(const QString &pubkey) const
return found;
}
/**
@brief Get the full address if known, or public key of a friend
*/
QString Core::getFriendAddress(uint32_t friendNumber) const
{
QString id = getFriendPublicKey(friendNumber);
@ -1110,6 +1173,9 @@ QString Core::getFriendAddress(uint32_t friendNumber) const
return id;
}
/**
@brief Get the public key part of the ToxID only
*/
QString Core::getFriendPublicKey(uint32_t friendNumber) const
{
uint8_t rawid[TOX_PUBLIC_KEY_SIZE];
@ -1124,6 +1190,9 @@ QString Core::getFriendPublicKey(uint32_t friendNumber) const
return id;
}
/**
@brief Get the username of a friend
*/
QString Core::getFriendUsername(uint32_t friendnumber) const
{
size_t namesize = tox_friend_get_name_size(tox, friendnumber, nullptr);
@ -1197,6 +1266,9 @@ QString Core::getPeerName(const ToxId& id) const
return name;
}
/**
@brief Most of the API shouldn't be used until Core is ready, call start() first
*/
bool Core::isReady()
{
return av && av->getToxAv() && tox && ready;
@ -1211,6 +1283,9 @@ void Core::setNospam(uint32_t nospam)
emit idSet(getSelfId().toString());
}
/**
@brief Returns the unencrypted tox save data
*/
void Core::killTimers(bool onlyStop)
{
assert(QThread::currentThread() == coreThread);
@ -1223,6 +1298,10 @@ void Core::killTimers(bool onlyStop)
}
}
/**
@brief Reinitialized the core.
@warning Must be called from the Core thread, with the GUI thread ready to process events.
*/
void Core::reset()
{
assert(QThread::currentThread() == coreThread);

View File

@ -46,7 +46,7 @@ class Core : public QObject
Q_OBJECT
public:
explicit Core(QThread* coreThread, Profile& profile);
static Core* getInstance(); ///< Returns the global widget's Core instance
static Core* getInstance();
CoreAV* getAv();
~Core();
@ -59,41 +59,42 @@ public:
QString getPeerName(const ToxId& id) const;
QVector<uint32_t> getFriendList() const; ///< Returns the list of friendIds in our friendlist, an empty list on error
int getGroupNumberPeers(int groupId) const; ///< Return the number of peers in the group chat on success, or -1 on failure
QString getGroupPeerName(int groupId, int peerId) const; ///< Get the name of a peer of a group
ToxId getGroupPeerToxId(int groupId, int peerId) const; ///< Get the public key of a peer of a group
QList<QString> getGroupPeerNames(int groupId) const; ///< Get the names of the peers of a group
QString getFriendAddress(uint32_t friendNumber) const; ///< Get the full address if known, or public key of a friend
QString getFriendPublicKey(uint32_t friendNumber) const; ///< Get the public key part of the ToxID only
QString getFriendUsername(uint32_t friendNumber) const; ///< Get the username of a friend
bool isFriendOnline(uint32_t friendId) const; ///< Check if a friend is online. Unknown friends are considered offline.
bool hasFriendWithAddress(const QString &addr) const; ///< Check if we have a friend by address
bool hasFriendWithPublicKey(const QString &pubkey) const; ///< Check if we have a friend by public key
int joinGroupchat(int32_t friendId, uint8_t type, const uint8_t* pubkey,uint16_t length) const; ///< Accept a groupchat invite
void quitGroupChat(int groupId) const; ///< Quit a groupchat
QVector<uint32_t> getFriendList() const;
int getGroupNumberPeers(int groupId) const;
QString getGroupPeerName(int groupId, int peerId) const;
ToxId getGroupPeerToxId(int groupId, int peerId) const;
QList<QString> getGroupPeerNames(int groupId) const;
QString getFriendAddress(uint32_t friendNumber) const;
QString getFriendPublicKey(uint32_t friendNumber) const;
QString getFriendUsername(uint32_t friendNumber) const;
QString getUsername() const; ///< Returns our username, or an empty string on failure
Status getStatus() const; ///< Returns our user status
QString getStatusMessage() const; ///< Returns our status message, or an empty string on failure
ToxId getSelfId() const; ///< Returns our Tox ID
QPair<QByteArray, QByteArray> getKeypair() const; ///< Returns our public and private keys
bool isFriendOnline(uint32_t friendId) const;
bool hasFriendWithAddress(const QString &addr) const;
bool hasFriendWithPublicKey(const QString &pubkey) const;
int joinGroupchat(int32_t friendId, uint8_t type, const uint8_t* pubkey,uint16_t length) const;
void quitGroupChat(int groupId) const;
QString getUsername() const;
Status getStatus() const;
QString getStatusMessage() const;
ToxId getSelfId() const;
QPair<QByteArray, QByteArray> getKeypair() const;
static std::unique_ptr<TOX_PASS_KEY> createPasskey(const QString &password, uint8_t* salt = nullptr);
static QByteArray encryptData(const QByteArray& data, const TOX_PASS_KEY& encryptionKey);
static QByteArray encryptData(const QByteArray& data); ///< Uses the default profile's key
static QByteArray encryptData(const QByteArray& data);
static QByteArray decryptData(const QByteArray& data, const TOX_PASS_KEY &encryptionKey);
static QByteArray decryptData(const QByteArray& data); ///< Uses the default profile's key
static QByteArray decryptData(const QByteArray& data);
bool isReady(); ///< Most of the API shouldn't be used until Core is ready, call start() first
bool isReady();
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.
void process(); ///< Processes toxcore events and ensure we stay connected, called by its own timer
void bootstrapDht(); ///< Connects us to the Tox network
void start();
void reset();
void process();
void bootstrapDht();
QByteArray getToxSaveData(); ///< Returns the unencrypted tox save data
QByteArray getToxSaveData();
void acceptFriendRequest(const QString& userId);
void requestFriendship(const QString& friendAddress, const QString& message);
@ -225,7 +226,7 @@ private:
void deadifyTox();
private slots:
void killTimers(bool onlyStop); ///< Must only be called from the Core thread
void killTimers(bool onlyStop);
private:
Tox* tox;

View File

@ -31,7 +31,52 @@
#include <QCoreApplication>
#include <QtConcurrent/QtConcurrentRun>
/**
@fn void CoreAV::avInvite(uint32_t friendId, bool video)
@brief Sent when a friend calls us.
@param friendId Id of friend in call list.
@param video False if chat is audio only, true audio and video.
@fn void CoreAV::avStart(uint32_t friendId, bool video)
@brief Sent when a call we initiated has started.
@param friendId Id of friend in call list.
@param video False if chat is audio only, true audio and video.
@fn void CoreAV::avEnd(uint32_t friendId)
@brief Sent when a call was ended by the peer.
@param friendId Id of friend in call list.
*/
/**
@var CoreAV::AUDIO_DEFAULT_BITRATE
@brief In kb/s. More than enough for Opus.
@var CoreAV::VIDEO_DEFAULT_BITRATE
@brief Picked at random by fair dice roll.
*/
/**
@var std::atomic_flag CoreAV::threadSwitchLock
@brief This flag is to be acquired before switching in a blocking way between the UI and CoreAV thread.
The CoreAV thread must have priority for the flag, other threads should back off or release it quickly.
CoreAV needs to interface with three threads, the toxcore/Core thread that fires non-payload
toxav callbacks, the toxav/CoreAV thread that fires AV payload callbacks and manages
most of CoreAV's members, and the UI thread, which calls our [start/answer/cancel]Call functions
and which we call via signals.
When the UI calls us, we switch from the UI thread to the CoreAV thread to do the processing,
when toxcore fires a non-payload av callback, we do the processing in the CoreAV thread and then
switch to the UI thread to send it a signal. Both switches block both threads, so this would deadlock.
*/
/**
@brief Maps friend IDs to ToxFriendCall.
*/
IndexedList<ToxFriendCall> CoreAV::calls;
/**
@brief Maps group IDs to ToxGroupCalls.
*/
IndexedList<ToxGroupCall> CoreAV::groupCalls;
using namespace std;
@ -76,6 +121,9 @@ const ToxAV *CoreAV::getToxAv() const
return toxav;
}
/**
@brief Starts the CoreAV main loop that calls toxav's main loop
*/
void CoreAV::start()
{
// Timers can only be touched from their own thread
@ -84,6 +132,9 @@ void CoreAV::start()
iterateTimer->start();
}
/**
@brief Stops the main loop
*/
void CoreAV::stop()
{
// Timers can only be touched from their own thread
@ -92,6 +143,9 @@ void CoreAV::stop()
iterateTimer->stop();
}
/**
@brief Calls itself blocking queued on the coreav thread
*/
void CoreAV::killTimerFromThread()
{
// Timers can only be touched from their own thread
@ -106,6 +160,11 @@ void CoreAV::process()
iterateTimer->start(toxav_iteration_interval(toxav));
}
/**
@brief Check, that and calls are active now
@return True is any calls are currently active, False otherwise
@note A call about to start is not yet active
*/
bool CoreAV::anyActiveCalls()
{
return !calls.isEmpty();
@ -234,6 +293,15 @@ void CoreAV::timeoutCall(uint32_t friendNum)
emit avEnd(friendNum);
}
/**
@brief Send audio frame to a friend
@param callId Id of friend in call list.
@param pcm An array of audio samples (Pulse-code modulation).
@param samples Number of samples in this frame.
@param chans Number of audio channels.
@param rate Audio sampling rate used in this frame.
@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, uint32_t rate)
{
if (!calls.contains(callId))
@ -378,6 +446,11 @@ void CoreAV::groupCallCallback(void* tox, int group, int peer,
sample_rate);
}
/**
@brief Get a call's video source.
@param friendNum Id of friend in call list.
@return Video surface to show
*/
VideoSource *CoreAV::getVideoSourceFromCall(int friendNum)
{
if (!calls.contains(friendNum))
@ -389,6 +462,11 @@ VideoSource *CoreAV::getVideoSourceFromCall(int friendNum)
return calls[friendNum].videoSource;
}
/**
@brief Starts a call in an existing AV groupchat.
@note Call from the GUI thread.
@param groupId Id of group to join
*/
void CoreAV::joinGroupCall(int groupId)
{
qDebug() << QString("Joining group call %1").arg(groupId);
@ -397,6 +475,11 @@ void CoreAV::joinGroupCall(int groupId)
call->inactive = false;
}
/**
@brief Will not leave the group, just stop the call.
@note Call from the GUI thread.
@param groupId Id of group to leave
*/
void CoreAV::leaveGroupCall(int groupId)
{
qDebug() << QString("Leaving group call %1").arg(groupId);
@ -450,11 +533,19 @@ bool CoreAV::isGroupCallVolEnabled(int groupId) const
return !groupCalls[groupId].muteVol;
}
/**
@brief Check, that group has audio or video stream
@param groupId Id of group to check
@return True for AV groups, false for text-only groups
*/
bool CoreAV::isGroupAvEnabled(int groupId) const
{
return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV;
}
/**
@brief Forces to regenerate each call's audio sources.
*/
void CoreAV::invalidateCallSources()
{
for (ToxGroupCall& call : groupCalls)
@ -468,6 +559,10 @@ void CoreAV::invalidateCallSources()
}
}
/**
@brief Signal to all peers that we're not sending video anymore.
@note The next frame sent cancels this.
*/
void CoreAV::sendNoVideo()
{
// We don't change the audio bitrate, but we signal that we're not sending video anymore

View File

@ -46,26 +46,25 @@ public:
const ToxAV* getToxAv() const;
bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
bool anyActiveCalls();
bool isCallVideoEnabled(uint32_t friendNum);
/// Returns false only on error, but not if there's nothing to send
bool sendCallAudio(uint32_t friendNum, const int16_t *pcm, size_t samples, uint8_t chans, uint32_t rate);
void sendCallVideo(uint32_t friendNum, std::shared_ptr<VideoFrame> frame);
bool sendGroupCallAudio(int groupNum, const int16_t *pcm, size_t samples, uint8_t chans, uint32_t rate);
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
void invalidateCallSources(); ///< Forces to regenerate each call's audio sources
void sendNoVideo(); ///< Signal to all peers that we're not sending video anymore. The next frame sent cancels this.
VideoSource* getVideoSourceFromCall(int callNumber);
void invalidateCallSources();
void sendNoVideo();
void joinGroupCall(int groupNum); ///< Starts a call in an existing AV groupchat. Call from the GUI thread.
void leaveGroupCall(int groupNum); ///< Will not leave the group, just stop the call. Call from the GUI thread.
void joinGroupCall(int groupNum);
void leaveGroupCall(int groupNum);
void disableGroupCallMic(int groupNum);
void disableGroupCallVol(int groupNum);
void enableGroupCallMic(int groupNum);
void enableGroupCallVol(int groupNum);
bool isGroupCallMicEnabled(int groupNum) const;
bool isGroupCallVolEnabled(int groupNum) const;
bool isGroupAvEnabled(int groupNum) const; ///< True for AV groups, false for text-only groups
bool isGroupAvEnabled(int groupNum) const;
void micMuteToggle(uint32_t friendNum);
void volMuteToggle(uint32_t friendNum);
@ -80,21 +79,19 @@ public slots:
bool answerCall(uint32_t friendNum);
bool cancelCall(uint32_t friendNum);
void timeoutCall(uint32_t friendNum);
/// Starts the CoreAV main loop that calls toxav's main loop
void start();
/// Stops the main loop
void stop();
signals:
void avInvite(uint32_t friendId, bool video); ///< Sent when a friend calls us
void avStart(uint32_t friendId, bool video); ///< Sent when a call we initiated has started
void avEnd(uint32_t friendId); ///< Sent when a call was ended by the peer
void avInvite(uint32_t friendId, bool video);
void avStart(uint32_t friendId, bool video);
void avEnd(uint32_t friendId);
private slots:
static void callCallback(ToxAV *toxAV, uint32_t friendNum, bool audio, bool video, void* self);
static void stateCallback(ToxAV *, uint32_t friendNum, uint32_t state, void* self);
static void bitrateCallback(ToxAV *toxAV, uint32_t friendNum, uint32_t arate, uint32_t vrate, void* self);
void killTimerFromThread(); ///< Calls itself blocking queued on the coreav thread
void killTimerFromThread();
private:
void process();
@ -105,27 +102,15 @@ private:
int32_t ystride, int32_t ustride, int32_t vstride, void* self);
private:
static constexpr uint32_t AUDIO_DEFAULT_BITRATE = 64; ///< In kb/s. More than enough for Opus.
static constexpr uint32_t VIDEO_DEFAULT_BITRATE = 6144; ///< Picked at random by fair dice roll.
static constexpr uint32_t AUDIO_DEFAULT_BITRATE = 64;
static constexpr uint32_t VIDEO_DEFAULT_BITRATE = 6144;
private:
ToxAV* toxav;
std::unique_ptr<QThread> coreavThread;
std::unique_ptr<QTimer> iterateTimer;
static IndexedList<ToxFriendCall> calls;
static IndexedList<ToxGroupCall> groupCalls; // Maps group IDs to ToxGroupCalls
/**
* This flag is to be acquired before switching in a blocking way between the UI and CoreAV thread.
* The CoreAV thread must have priority for the flag, other threads should back off or release it quickly.
*
* CoreAV needs to interface with three threads, the toxcore/Core thread that fires non-payload
* toxav callbacks, the toxav/CoreAV thread that fires AV payload callbacks and manages
* most of CoreAV's members, and the UI thread, which calls our [start/answer/cancel]Call functions
* and which we call via signals.
* When the UI calls us, we switch from the UI thread to the CoreAV thread to do the processing,
* when toxcore fires a non-payload av callback, we do the processing in the CoreAV thread and then
* switch to the UI thread to send it a signal. Both switches block both threads, so this would deadlock.
*/
static IndexedList<ToxGroupCall> groupCalls;
std::atomic_flag threadSwitchLock;
friend class Audio;

View File

@ -51,6 +51,12 @@ std::unique_ptr<TOX_PASS_KEY> Core::createPasskey(const QString& password, uint8
return encryptionKey;
}
/**
@brief Encrypts data.
@note Uses the default profile's key.
@param data Data to encrypt.
@return Encrypted data.
*/
QByteArray Core::encryptData(const QByteArray &data)
{
return encryptData(data, Nexus::getProfile()->getPasskey());
@ -68,6 +74,12 @@ QByteArray Core::encryptData(const QByteArray& data, const TOX_PASS_KEY& encrypt
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
}
/**
@brief Decrypts data.
@note Uses the default profile's key.
@param data Data to decrypt.
@return Decrypted data.
*/
QByteArray Core::decryptData(const QByteArray &data)
{
return decryptData(data, Nexus::getProfile()->getPasskey());

View File

@ -30,14 +30,27 @@
#include <QDir>
#include <memory>
/**
@class CoreFile
@brief Implements Core's file transfer callbacks.
Avoids polluting core.h with private internal callbacks.
*/
QMutex CoreFile::fileSendMutex;
QHash<uint64_t, ToxFile> CoreFile::fileMap;
using namespace std;
/**
@brief Get corefile iteration interval.
tox_iterate calls to get good file transfer performances
@return The maximum amount of time in ms that Core should wait between two tox_iterate() calls.
*/
unsigned CoreFile::corefileIterationInterval()
{
/// Sleep at most 1000ms if we have no FT, 10 for user FTs, 50 for the rest (avatars, ...)
constexpr unsigned fastFileInterval=10, slowFileInterval=50, idleInterval=1000;
constexpr unsigned fastFileInterval = 10, slowFileInterval = 50, idleInterval = 1000;
unsigned interval = idleInterval;
for (ToxFile& file : fileMap)

View File

@ -35,8 +35,6 @@
struct Tox;
class Core;
/// Implements Core's file transfer callbacks
/// Avoids polluting core.h with private internal callbacks
class CoreFile
{
friend class Core;
@ -57,8 +55,6 @@ private:
static ToxFile *findFile(uint32_t friendId, uint32_t fileId);
static void addFile(uint32_t friendId, uint32_t fileId, const ToxFile& file);
static void removeFile(uint32_t friendId, uint32_t fileId);
/// Returns the maximum amount of time in ms that Core should wait between two
/// tox_iterate calls to get good file transfer performances
static unsigned corefileIterationInterval();
private:

View File

@ -6,6 +6,18 @@
#define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE
/**
@file corestructs.h
@brief Some headers use Core structs but don't need to include all of core.h
They should include this file directly instead to reduce compilation times
*/
/**
@var uint8_t ToxFile::fileKind
@brief Data file (default) or avatar
*/
ToxFile::ToxFile(uint32_t fileNum, uint32_t friendId, QByteArray filename, QString filePath, FileDirection Direction)
: fileKind{TOX_FILE_KIND_DATA}, fileNum(fileNum), friendId(friendId), fileName{filename},
filePath{filePath}, file{new QFile(filePath)}, bytesSent{0}, filesize{0},

View File

@ -1,11 +1,9 @@
#ifndef CORESTRUCTS_H
#define CORESTRUCTS_H
// Some headers use Core structs but don't need to include all of core.h
// They should include this file directly instead to reduce compilation times
#include <QString>
#include <memory>
class QFile;
class QTimer;
@ -35,7 +33,7 @@ struct ToxFile
RECEIVING
};
ToxFile()=default;
ToxFile() = default;
ToxFile(uint32_t FileNum, uint32_t FriendId, QByteArray FileName, QString filePath, FileDirection Direction);
~ToxFile(){}
@ -45,7 +43,7 @@ struct ToxFile
void setFilePath(QString path);
bool open(bool write);
uint8_t fileKind; ///< Data file (default) or avatar
uint8_t fileKind;
uint32_t fileNum;
uint32_t friendId;
QByteArray fileName;

View File

@ -4,8 +4,6 @@
#include <vector>
#include <algorithm>
/// More or less a hashmap, indexed by the noexcept move-only value type's operator int
/// Really nice to store our ToxCall objects.
template <typename T>
class IndexedList
{
@ -13,30 +11,72 @@ public:
explicit IndexedList() = default;
// Qt
inline bool isEmpty() { return v.empty(); }
bool contains(int i) { return std::find_if(begin(), end(), [i](T& t){return (int)t == i;}) != end(); }
void remove(int i) { v.erase(std::remove_if(begin(), end(), [i](T& t){return (int)t == i;}), end()); }
T& operator[](int i)
bool isEmpty()
{
return v.empty();
}
bool contains(int i)
{
return std::find_if(begin(), end(), [i](T& t){return (int)t == i;}) != end();
}
void remove(int i)
{
v.erase(std::remove_if(begin(), end(), [i](T& t){return (int)t == i;}), end());
}
T &operator[](int i)
{
iterator it = std::find_if(begin(), end(), [i](T& t){return (int)t == i;});
if (it == end())
it = insert({});
return *it;
}
// STL
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;
inline iterator begin() { return v.begin(); }
inline const_iterator begin() const { return v.begin(); }
inline const_iterator cbegin() const { return v.cbegin(); }
inline iterator end() { return v.end(); }
inline const_iterator end() const { return v.end(); }
inline const_iterator cend() const { return v.cend(); }
inline iterator erase(iterator pos) { return v.erase(pos); }
inline iterator erase(iterator first, iterator last) { return v.erase(first, last); }
inline iterator insert(T&& value) { v.push_back(std::move(value)); return --v.end(); }
inline iterator begin()
{
return v.begin();
}
inline const_iterator begin() const
{
return v.begin();
}
inline const_iterator cbegin() const
{
return v.cbegin();
}
inline iterator end()
{
return v.end();
}
inline const_iterator end() const
{
return v.end();
}
inline const_iterator cend() const
{
return v.cend();
}
inline iterator erase(iterator pos)
{
return v.erase(pos);
}
inline iterator erase(iterator first, iterator last)
{
return v.erase(first, last);
}
inline iterator insert(T&& value)
{
v.push_back(std::move(value));
return --v.end();
}
private:
std::vector<T> v;

View File

@ -7,6 +7,23 @@
#include <QTimer>
#include <QtConcurrent/QtConcurrent>
/**
@var uint32_t ToxCall::callId
@brief Could be a friendNum or groupNum, must uniquely identify the call. Do not modify!
@var bool ToxCall::inactive
@brief True while we're not participating. (stopped group call, ringing but hasn't started yet, ...)
@var bool ToxCall::videoEnabled
@brief True if our user asked for a video call, sending and recieving.
@var bool ToxCall::nullVideoBitrate
@brief True if our video bitrate is zero, i.e. if the device is closed.
@var TOXAV_FRIEND_CALL_STATE ToxCall::state
@brief State of the peer (not ours!)
*/
using namespace std;
ToxCall::ToxCall(uint32_t CallId)

View File

@ -32,9 +32,9 @@ protected:
QMetaObject::Connection audioInConn;
public:
uint32_t callId; ///< Could be a friendNum or groupNum, must uniquely identify the call. Do not modify!
uint32_t callId;
quint32 alSource;
bool inactive; ///< True while we're not participating. (stopped group call, ringing but hasn't started yet, ...)
bool inactive;
bool muteMic;
bool muteVol;
};
@ -48,10 +48,10 @@ struct ToxFriendCall : public ToxCall
ToxFriendCall& operator=(ToxFriendCall&& other) noexcept;
bool videoEnabled; ///< True if our user asked for a video call, sending and recving
bool nullVideoBitrate; ///< True if our video bitrate is zero, i.e. if the device is closed
bool videoEnabled;
bool nullVideoBitrate;
CoreVideoSource* videoSource;
TOXAV_FRIEND_CALL_STATE state; ///< State of the peer (not ours!)
TOXAV_FRIEND_CALL_STATE state;
void startTimeout();
void stopTimeout();

View File

@ -30,14 +30,46 @@
#define TOX_ID_CHECKSUM_LENGTH 4
#define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE
/**
@class ToxId
@brief This class represents a Tox ID.
An ID is composed of 32 bytes long public key, 4 bytes long NoSpam
and 2 bytes long checksum.
e.g.
@code
| C7719C6808C14B77348004956D1D98046CE09A34370E7608150EAD74C3815D30 | C8BA3AB9 | BEB9
| / |
| / NoSpam | Checksum
| Public Key (PK), 32 bytes, 64 characters / 4 bytes | 2 bytes
| | 8 characters| 4 characters
@endcode
*/
/**
@brief The default constructor. Creates an empty Tox ID.
*/
ToxId::ToxId()
: publicKey(), noSpam(), checkSum()
{}
/**
@brief The copy constructor.
@param other ToxId to copy
*/
ToxId::ToxId(const ToxId &other)
: publicKey(other.publicKey), noSpam(other.noSpam), checkSum(other.checkSum)
{}
/**
@brief Create a Tox ID from QString.
If the given id is not a valid Tox ID, then:
publicKey == id and noSpam == "" == checkSum.
@param id Tox ID string to convert to ToxId object
*/
ToxId::ToxId(const QString &id)
{
if (isToxId(id))
@ -52,26 +84,48 @@ ToxId::ToxId(const QString &id)
}
}
/**
@brief Compares, that public key equals.
@param other Tox ID to compare.
@return True if both Tox ID have same public keys, false otherwise.
*/
bool ToxId::operator==(const ToxId& other) const
{
return publicKey == other.publicKey;
}
/**
@brief Compares, that only public key not equals.
@param other Tox ID to compare.
@return True if both Tox ID have different public keys, false otherwise.
*/
bool ToxId::operator!=(const ToxId &other) const
{
return publicKey != other.publicKey;
}
/**
@brief Check, that the current user ID is the active user ID
@return True if this Tox ID is equals to
the Tox ID of the currently active profile.
*/
bool ToxId::isSelf() const
{
return *this == Core::getInstance()->getSelfId();
}
/**
@brief Returns Tox ID converted to QString.
@return The Tox ID as QString.
*/
QString ToxId::toString() const
{
return publicKey + noSpam + checkSum;
}
/**
@brief Clears all elements of the Tox ID.
*/
void ToxId::clear()
{
publicKey.clear();
@ -79,6 +133,11 @@ void ToxId::clear()
checkSum.clear();
}
/**
@brief Check, that id is a valid Tox ID.
@param id Tox ID to check.
@return True if id is a valid Tox ID, false otherwise.
*/
bool ToxId::isToxId(const QString &id)
{
const QRegularExpression hexRegExp("^[A-Fa-f0-9]+$");

View File

@ -23,36 +23,20 @@
#include <QString>
/*
* This class represents a Tox ID.
* An ID is composed of 32 bytes long public key, 4 bytes long NoSpam
* and 2 bytes long checksum.
*
* e.g.
*
* | C7719C6808C14B77348004956D1D98046CE09A34370E7608150EAD74C3815D30 | C8BA3AB9 | BEB9
* | / |
* | / NoSpam | Checksum
* | Public Key (PK), 32 bytes, 64 characters / 4 bytes | 2 bytes
* | | 8 characters| 4 characters
*/
class ToxId
{
public:
ToxId(); ///< The default constructor. Creates an empty Tox ID.
ToxId(const ToxId& other); ///< The copy constructor.
explicit ToxId(const QString& id); ///< Create a Tox ID from QString.
/// If the given id is not a valid Tox ID, then:
/// publicKey == id and noSpam == "" == checkSum.
ToxId();
ToxId(const ToxId& other);
explicit ToxId(const QString& id);
bool operator==(const ToxId& other) const; ///< Compares only publicKey.
bool operator!=(const ToxId& other) const; ///< Compares only publicKey.
bool isSelf() const; ///< Returns true if this Tox ID is equals to
/// the Tox ID of the currently active profile.
QString toString() const; ///< Returns the Tox ID as QString.
void clear(); ///< Clears all elements of the Tox ID.
bool operator==(const ToxId& other) const;
bool operator!=(const ToxId& other) const;
bool isSelf() const;
QString toString() const;
void clear();
static bool isToxId(const QString& id); ///< Returns true if id is a valid Tox ID.
static bool isToxId(const QString& id);
public:
QString publicKey;

View File

@ -51,6 +51,9 @@ Friend::~Friend()
delete widget;
}
/**
@brief Loads the friend's chat history if enabled
*/
void Friend::loadHistory()
{
if (Nexus::getProfile()->isHistoryEnabled())

View File

@ -37,7 +37,6 @@ public:
~Friend();
Friend& operator=(const Friend& other)=delete;
/// Loads the friend's chat history if enabled
void loadHistory();
void setName(QString name);

View File

@ -25,6 +25,19 @@
#include <random>
#include <unistd.h>
/**
@var time_t IPC::lastEvent
@brief When last event was posted.
@var time_t IPC::lastProcessed
@brief When processEvents() ran last time
*/
/**
@class IPC
@brief Inter-process communication
*/
IPC::IPC()
: globalMemory{"qtox-" IPC_PROTOCOL_VERSION}
{
@ -84,13 +97,23 @@ IPC::~IPC()
}
}
/**
@brief Returns the singleton instance.
*/
IPC& IPC::getInstance()
{
static IPC instance;
return instance;
}
time_t IPC::postEvent(const QString &name, const QByteArray& data/*=QByteArray()*/, uint32_t dest/*=0*/)
/**
@brief Post IPC event.
@param name Name to set in IPC event.
@param data Data to set in IPC event (default QByteArray()).
@param dest Settings::getCurrentProfileId() or 0 (main instance, default).
@return Time the event finished.
*/
time_t IPC::postEvent(const QString &name, const QByteArray& data, uint32_t dest)
{
QByteArray binName = name.toUtf8();
if (binName.length() > (int32_t)sizeof(IPCEvent::name))
@ -101,7 +124,7 @@ time_t IPC::postEvent(const QString &name, const QByteArray& data/*=QByteArray()
if (globalMemory.lock())
{
IPCEvent* evt = 0;
IPCEvent* evt = nullptr;
IPCMemory* mem = global();
time_t result = 0;
@ -195,6 +218,10 @@ bool IPC::waitUntilAccepted(time_t postTime, int32_t timeout/*=-1*/)
return result;
}
/**
@brief Only called when global memory IS LOCKED.
@return nullptr if no evnts present, IPC event otherwise
*/
IPC::IPCEvent *IPC::fetchEvent()
{
IPCMemory* mem = global();
@ -209,32 +236,28 @@ IPC::IPCEvent *IPC::fetchEvent()
(!evt->processed && difftime(time(0), evt->posted) > EVENT_GC_TIMEOUT))
memset(evt, 0, sizeof(IPCEvent));
if (evt->posted && !evt->processed && evt->sender != getpid())
{
if (evt->dest == Settings::getInstance().getCurrentProfileId() || (evt->dest == 0 && isCurrentOwner()))
return evt;
}
if (evt->posted && !evt->processed && evt->sender != getpid()
&& (evt->dest == Settings::getInstance().getCurrentProfileId()
|| (evt->dest == 0 && isCurrentOwner())))
return evt;
}
return 0;
return nullptr;
}
bool IPC::runEventHandler(IPCEventHandler handler, const QByteArray& arg)
{
bool result = false;
if (QThread::currentThread() != qApp->thread())
{
if (QThread::currentThread() == qApp->thread())
result = handler(arg);
else
QMetaObject::invokeMethod(this, "runEventHandler",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, result),
Q_ARG(IPCEventHandler, handler),
Q_ARG(const QByteArray&, arg));
return result;
}
else
{
result = handler(arg);
return result;
}
return result;
}
void IPC::processEvents()

View File

@ -64,14 +64,11 @@ public:
struct IPCMemory
{
uint64_t globalId;
// When last event was posted
time_t lastEvent;
// When processEvents() ran last time
time_t lastProcessed;
IPCEvent events[IPC::EVENT_QUEUE_SIZE];
};
// dest: Settings::getCurrentProfileId() or 0 (main instance).
time_t postEvent(const QString& name, const QByteArray &data=QByteArray(), uint32_t dest=0);
bool isCurrentOwner();
void registerEventHandler(const QString& name, IPCEventHandler handler);
@ -84,7 +81,6 @@ protected slots:
protected:
IPCMemory* global();
bool runEventHandler(IPCEventHandler handler, const QByteArray& arg);
// Only called when global memory IS LOCKED, returns 0 if no evnts present
IPCEvent* fetchEvent();
QTimer timer;

View File

@ -43,6 +43,14 @@
#include <QSignalMapper>
#endif
/**
@class Nexus
This class is in charge of connecting various systems together
and forwarding signals appropriately to the right objects,
it is in charge of starting the GUI and the Core.
*/
Q_DECLARE_OPAQUE_POINTER(ToxAV*)
static Nexus* nexus{nullptr};
@ -66,6 +74,11 @@ Nexus::~Nexus()
#endif
}
/**
Sets up invariants and calls showLogin
Hides the login screen and shows the GUI for the given profile.
Will delete the current GUI, if it exists.
*/
void Nexus::start()
{
qDebug() << "Starting up";
@ -131,6 +144,9 @@ void Nexus::start()
showLogin();
}
/**
@brief Hides the main GUI, delete the profile, and shows the login screen
*/
void Nexus::showLogin()
{
delete widget;
@ -201,6 +217,9 @@ void Nexus::showMainGUI()
profile->startCore();
}
/**
@brief Returns the singleton instance.
*/
Nexus& Nexus::getInstance()
{
if (!nexus)
@ -215,6 +234,10 @@ void Nexus::destroyInstance()
nexus = nullptr;
}
/**
@brief Get core instance.
@return nullptr if not started, core instance otherwise.
*/
Core* Nexus::getCore()
{
Nexus& nexus = getInstance();
@ -224,11 +247,19 @@ Core* Nexus::getCore()
return nexus.profile->getCore();
}
/**
@brief Get current user profile.
@return nullptr if not started, profile otherwise.
*/
Profile* Nexus::getProfile()
{
return getInstance().profile;
}
/**
@brief Unload the current profile, if any, and replaces it.
@param profile Profile to set.
*/
void Nexus::setProfile(Profile* profile)
{
getInstance().profile = profile;
@ -236,6 +267,10 @@ void Nexus::setProfile(Profile* profile)
Settings::getInstance().loadPersonal(profile);
}
/**
@brief Get desktop GUI widget.
@return nullptr if not started, desktop widget otherwise.
*/
Widget* Nexus::getDesktopGUI()
{
return getInstance().widget;
@ -250,6 +285,11 @@ QString Nexus::getSupportedImageFilter()
return tr("Images (%1)", "filetype filter").arg(res.left(res.size()-1));
}
/**
@brief Dangerous way to find out if a path is writable.
@param filepath Path to file which should be deleted.
@return True, if file writeable, false otherwise.
*/
bool Nexus::tryRemoveFile(const QString& filepath)
{
QFile tmp(filepath);
@ -258,6 +298,9 @@ bool Nexus::tryRemoveFile(const QString& filepath)
return writable;
}
/**
@brief Calls showLogin asynchronously, so we can safely logout from within the main GUI
*/
void Nexus::showLoginLater()
{
GUI::setEnabled(false);

View File

@ -37,30 +37,25 @@ class QActionGroup;
class QSignalMapper;
#endif
/// This class is in charge of connecting various systems together
/// and forwarding signals appropriately to the right objects
/// It is in charge of starting the GUI and the Core
class Nexus : public QObject
{
Q_OBJECT
public:
void start(); ///< Sets up invariants and calls showLogin
/// Hides the login screen and shows the GUI for the given profile.
/// Will delete the current GUI, if it exists.
void start();
void showMainGUI();
static Nexus& getInstance();
static void destroyInstance();
static Core* getCore(); ///< Will return 0 if not started
static Profile* getProfile(); ///< Will return 0 if not started
static void setProfile(Profile* profile); ///< Delete the current profile, if any, and replaces it
static Widget* getDesktopGUI(); ///< Will return 0 if not started
static Core* getCore();
static Profile* getProfile();
static void setProfile(Profile* profile);
static Widget* getDesktopGUI();
static QString getSupportedImageFilter();
static bool tryRemoveFile(const QString& filepath); ///< Dangerous way to find out if a path is writable
static bool tryRemoveFile(const QString& filepath);
public slots:
void showLogin(); ///< Hides the man GUI, delete the profile, and shows the login screen
void showLoginLater(); ///< Calls showLogin asynchronously, so we can safely logout from within the main GUI
void showLogin();
void showLoginLater();
#ifdef Q_OS_MAC
public: