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

refactor: Remove CameraSource singleton

Grossly expose it publicly from Nexus for the time being since Profile is
sometimes constructed from main, while Nexus is also a singleton. So
CameraSource can't be constructed in main and be passed in to Nexus on
construction. This should be temporary, until Nexus's singleton is
removed as well.
This commit is contained in:
Anthony Bilinski 2022-03-11 07:50:42 -08:00
parent 9bf17acca6
commit 61b3cb528a
No known key found for this signature in database
GPG Key ID: 2AA8E0DA1B31FB3C
19 changed files with 86 additions and 70 deletions

View File

@ -71,7 +71,7 @@
*/ */
CoreAV::CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> toxav_, CompatibleRecursiveMutex& toxCoreLock, CoreAV::CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> toxav_, CompatibleRecursiveMutex& toxCoreLock,
IAudioSettings& audioSettings_, IGroupSettings& groupSettings_) IAudioSettings& audioSettings_, IGroupSettings& groupSettings_, CameraSource& cameraSource_)
: audio{nullptr} : audio{nullptr}
, toxav{std::move(toxav_)} , toxav{std::move(toxav_)}
, coreavThread{new QThread{this}} , coreavThread{new QThread{this}}
@ -79,6 +79,7 @@ CoreAV::CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> toxav_, CompatibleRecursiveM
, coreLock{toxCoreLock} , coreLock{toxCoreLock}
, audioSettings{audioSettings_} , audioSettings{audioSettings_}
, groupSettings{groupSettings_} , groupSettings{groupSettings_}
, cameraSource{cameraSource_}
{ {
assert(coreavThread); assert(coreavThread);
assert(iterateTimer); assert(iterateTimer);
@ -111,7 +112,8 @@ void CoreAV::connectCallbacks()
* @return CoreAV instance on success, {} on failure * @return CoreAV instance on success, {} on failure
*/ */
CoreAV::CoreAVPtr CoreAV::makeCoreAV(Tox* core, CompatibleRecursiveMutex& toxCoreLock, CoreAV::CoreAVPtr CoreAV::makeCoreAV(Tox* core, CompatibleRecursiveMutex& toxCoreLock,
IAudioSettings& audioSettings, IGroupSettings& groupSettings) IAudioSettings& audioSettings, IGroupSettings& groupSettings,
CameraSource& cameraSource)
{ {
Toxav_Err_New err; Toxav_Err_New err;
std::unique_ptr<ToxAV, ToxAVDeleter> toxav{toxav_new(core, &err)}; std::unique_ptr<ToxAV, ToxAVDeleter> toxav{toxav_new(core, &err)};
@ -131,7 +133,8 @@ CoreAV::CoreAVPtr CoreAV::makeCoreAV(Tox* core, CompatibleRecursiveMutex& toxCor
assert(toxav != nullptr); assert(toxav != nullptr);
return CoreAVPtr{new CoreAV{std::move(toxav), toxCoreLock, audioSettings, groupSettings}}; return CoreAVPtr{new CoreAV{std::move(toxav), toxCoreLock, audioSettings,
groupSettings, cameraSource}};
} }
/** /**
@ -288,7 +291,8 @@ bool CoreAV::startCall(uint32_t friendNum, bool video)
// Audio backend must be set before making a call // Audio backend must be set before making a call
assert(audio != nullptr); assert(audio != nullptr);
ToxFriendCallPtr call = ToxFriendCallPtr(new ToxFriendCall(friendNum, video, *this, *audio)); ToxFriendCallPtr call = ToxFriendCallPtr(new ToxFriendCall(friendNum, video,
*this, *audio, cameraSource));
// Call object must be owned by this thread or there will be locking problems with Audio // Call object must be owned by this thread or there will be locking problems with Audio
call->moveToThread(thread()); call->moveToThread(thread());
assert(call != nullptr); assert(call != nullptr);
@ -722,7 +726,8 @@ void CoreAV::callCallback(ToxAV* toxav, uint32_t friendNum, bool audio, bool vid
// Audio backend must be set before receiving a call // Audio backend must be set before receiving a call
assert(self->audio != nullptr); assert(self->audio != nullptr);
ToxFriendCallPtr call = ToxFriendCallPtr(new ToxFriendCall{friendNum, video, *self, *self->audio}); ToxFriendCallPtr call = ToxFriendCallPtr(new ToxFriendCall{friendNum, video,
*self, *self->audio, self->cameraSource});
// Call object must be owned by CoreAV thread or there will be locking problems with Audio // Call object must be owned by CoreAV thread or there will be locking problems with Audio
call->moveToThread(self->thread()); call->moveToThread(self->thread());
assert(call != nullptr); assert(call != nullptr);

View File

@ -51,7 +51,8 @@ class CoreAV : public QObject
public: public:
using CoreAVPtr = std::unique_ptr<CoreAV>; using CoreAVPtr = std::unique_ptr<CoreAV>;
static CoreAVPtr makeCoreAV(Tox* core, CompatibleRecursiveMutex& toxCoreLock, static CoreAVPtr makeCoreAV(Tox* core, CompatibleRecursiveMutex& toxCoreLock,
IAudioSettings& audioSettings, IGroupSettings& groupSettings); IAudioSettings& audioSettings, IGroupSettings& groupSettings,
CameraSource&);
void setAudio(IAudioControl& newAudio); void setAudio(IAudioControl& newAudio);
IAudioControl* getAudio(); IAudioControl* getAudio();
@ -118,7 +119,7 @@ private:
}; };
CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> tox_, CompatibleRecursiveMutex &toxCoreLock, CoreAV(std::unique_ptr<ToxAV, ToxAVDeleter> tox_, CompatibleRecursiveMutex &toxCoreLock,
IAudioSettings& audioSettings_, IGroupSettings& groupSettings_); IAudioSettings& audioSettings_, IGroupSettings& groupSettings_, CameraSource&);
void connectCallbacks(); void connectCallbacks();
void process(); void process();
@ -165,4 +166,5 @@ private:
IAudioSettings& audioSettings; IAudioSettings& audioSettings;
IGroupSettings& groupSettings; IGroupSettings& groupSettings;
CameraSource& cameraSource;
}; };

View File

@ -59,7 +59,6 @@ ToxCall::~ToxCall()
{ {
if (videoEnabled) { if (videoEnabled) {
QObject::disconnect(videoInConn); QObject::disconnect(videoInConn);
CameraSource::getInstance().unsubscribe();
} }
} }
@ -118,10 +117,12 @@ CoreVideoSource* ToxCall::getVideoSource() const
return videoSource; return videoSource;
} }
ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av_, IAudioControl& audio_) ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av_,
IAudioControl& audio_, CameraSource& cameraSource_)
: ToxCall(VideoEnabled, av_, audio_) : ToxCall(VideoEnabled, av_, audio_)
, sink(audio_.makeSink()) , sink(audio_.makeSink())
, friendId{FriendNum} , friendId{FriendNum}
, cameraSource{cameraSource_}
{ {
connect(audioSource.get(), &IAudioSource::frameAvailable, this, connect(audioSource.get(), &IAudioSource::frameAvailable, this,
[this](const int16_t* pcm, size_t samples, uint8_t chans, uint32_t rate) { [this](const int16_t* pcm, size_t samples, uint8_t chans, uint32_t rate) {
@ -137,13 +138,12 @@ ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av_,
// register video // register video
if (videoEnabled) { if (videoEnabled) {
videoSource = new CoreVideoSource(); videoSource = new CoreVideoSource();
CameraSource& source = CameraSource::getInstance();
if (source.isNone()) { if (cameraSource.isNone()) {
source.setupDefault(); cameraSource.setupDefault();
} }
source.subscribe(); cameraSource.subscribe();
videoInConn = QObject::connect(&source, &VideoSource::frameAvailable, videoInConn = QObject::connect(&cameraSource, &VideoSource::frameAvailable,
[&av_, FriendNum](std::shared_ptr<VideoFrame> frame) { [&av_, FriendNum](std::shared_ptr<VideoFrame> frame) {
av_.sendCallVideo(FriendNum, frame); av_.sendCallVideo(FriendNum, frame);
}); });
@ -155,6 +155,9 @@ ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av_,
ToxFriendCall::~ToxFriendCall() ToxFriendCall::~ToxFriendCall()
{ {
if (videoEnabled) {
cameraSource.unsubscribe();
}
QObject::disconnect(audioSinkInvalid); QObject::disconnect(audioSinkInvalid);
} }

View File

@ -37,6 +37,7 @@ class AudioFilterer;
class CoreVideoSource; class CoreVideoSource;
class CoreAV; class CoreAV;
class Group; class Group;
class CameraSource;
class ToxCall : public QObject class ToxCall : public QObject
{ {
@ -91,7 +92,7 @@ class ToxFriendCall : public ToxCall
Q_OBJECT Q_OBJECT
public: public:
ToxFriendCall() = delete; ToxFriendCall() = delete;
ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av_, IAudioControl& audio_); ToxFriendCall(uint32_t friendId, bool VideoEnabled, CoreAV& av_, IAudioControl& audio_, CameraSource&);
ToxFriendCall(ToxFriendCall&& other) = delete; ToxFriendCall(ToxFriendCall&& other) = delete;
ToxFriendCall& operator=(ToxFriendCall&& other) = delete; ToxFriendCall& operator=(ToxFriendCall&& other) = delete;
~ToxFriendCall(); ~ToxFriendCall();
@ -110,6 +111,7 @@ private:
TOXAV_FRIEND_CALL_STATE state{TOXAV_FRIEND_CALL_STATE_NONE}; TOXAV_FRIEND_CALL_STATE state{TOXAV_FRIEND_CALL_STATE_NONE};
std::unique_ptr<IAudioSink> sink; std::unique_ptr<IAudioSink> sink;
uint32_t friendId; uint32_t friendId;
CameraSource& cameraSource;
}; };
class ToxGroupCall : public ToxCall class ToxGroupCall : public ToxCall

View File

@ -67,7 +67,6 @@ void cleanup()
s.sync(); s.sync();
Nexus::destroyInstance(); Nexus::destroyInstance();
CameraSource::destroyInstance();
Settings::destroyInstance(); Settings::destroyInstance();
qDebug() << "Cleanup success"; qDebug() << "Cleanup success";
@ -400,13 +399,13 @@ int main(int argc, char* argv[])
// note: Because Settings is shouldering global settings as well as model specific ones it // note: Because Settings is shouldering global settings as well as model specific ones it
// cannot be integrated into a central model object yet // cannot be integrated into a central model object yet
nexus.setSettings(&settings); nexus.setSettings(&settings);
auto& cameraSource = Nexus::getCameraSource();
// Autologin // Autologin
// TODO (kriby): Shift responsibility of linking views to model objects from nexus // TODO (kriby): Shift responsibility of linking views to model objects from nexus
// Further: generate view instances separately (loginScreen, mainGUI, audio) // Further: generate view instances separately (loginScreen, mainGUI, audio)
Profile* profile = nullptr; Profile* profile = nullptr;
if (autoLogin && Profile::exists(profileName) && !Profile::isEncrypted(profileName)) { if (autoLogin && Profile::exists(profileName) && !Profile::isEncrypted(profileName)) {
profile = Profile::loadProfile(profileName, QString(), settings, &parser); profile = Profile::loadProfile(profileName, QString(), settings, &parser, cameraSource);
if (!profile) { if (!profile) {
QMessageBox::information(nullptr, QObject::tr("Error"), QMessageBox::information(nullptr, QObject::tr("Error"),
QObject::tr("Failed to load profile automatically.")); QObject::tr("Failed to load profile automatically."));

View File

@ -63,7 +63,10 @@ Nexus::Nexus(QObject* parent)
: QObject(parent) : QObject(parent)
, profile{nullptr} , profile{nullptr}
, widget{nullptr} , widget{nullptr}
{} , cameraSource(new CameraSource())
{
assert(cameraSource);
}
Nexus::~Nexus() Nexus::~Nexus()
{ {
@ -228,7 +231,7 @@ void Nexus::showMainGUI()
assert(profile); assert(profile);
// Create GUI // Create GUI
widget = new Widget(*profile, *audioControl); widget = new Widget(*profile, *audioControl, *cameraSource);
// Start GUI // Start GUI
widget->init(); widget->init();
@ -301,7 +304,7 @@ Profile* Nexus::getProfile()
*/ */
void Nexus::onCreateNewProfile(const QString& name, const QString& pass) void Nexus::onCreateNewProfile(const QString& name, const QString& pass)
{ {
setProfile(Profile::createProfile(name, pass, *settings, parser)); setProfile(Profile::createProfile(name, pass, *settings, parser, *cameraSource));
parser = nullptr; // only apply cmdline proxy settings once parser = nullptr; // only apply cmdline proxy settings once
} }
@ -310,7 +313,7 @@ void Nexus::onCreateNewProfile(const QString& name, const QString& pass)
*/ */
void Nexus::onLoadProfile(const QString& name, const QString& pass) void Nexus::onLoadProfile(const QString& name, const QString& pass)
{ {
setProfile(Profile::loadProfile(name, pass, *settings, parser)); setProfile(Profile::loadProfile(name, pass, *settings, parser, *cameraSource));
parser = nullptr; // only apply cmdline proxy settings once parser = nullptr; // only apply cmdline proxy settings once
} }
/** /**
@ -344,6 +347,11 @@ Widget* Nexus::getDesktopGUI()
return getInstance().widget; return getInstance().widget;
} }
CameraSource& Nexus::getCameraSource()
{
return *getInstance().cameraSource;
}
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
void Nexus::retranslateUi() void Nexus::retranslateUi()
{ {

View File

@ -20,9 +20,11 @@
#pragma once #pragma once
#include "audio/iaudiocontrol.h"
#include <QObject> #include <QObject>
#include "audio/iaudiocontrol.h" #include <memory>
class Widget; class Widget;
class Profile; class Profile;
@ -30,6 +32,7 @@ class Settings;
class LoginScreen; class LoginScreen;
class Core; class Core;
class QCommandLineParser; class QCommandLineParser;
class CameraSource;
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
class QMenuBar; class QMenuBar;
@ -53,6 +56,7 @@ public:
static Core* getCore(); static Core* getCore();
static Profile* getProfile(); static Profile* getProfile();
static Widget* getDesktopGUI(); static Widget* getDesktopGUI();
static CameraSource& getCameraSource();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -104,4 +108,5 @@ private:
Widget* widget; Widget* widget;
std::unique_ptr<IAudioControl> audioControl; std::unique_ptr<IAudioControl> audioControl;
QCommandLineParser* parser = nullptr; QCommandLineParser* parser = nullptr;
std::unique_ptr<CameraSource> cameraSource;
}; };

View File

@ -232,7 +232,7 @@ bool logCreateToxDataError(const CreateToxDataError& error, const QString& userN
QStringList Profile::profiles; QStringList Profile::profiles;
void Profile::initCore(const QByteArray& toxsave, Settings& s, bool isNewProfile) void Profile::initCore(const QByteArray& toxsave, Settings& s, bool isNewProfile, CameraSource& cameraSource)
{ {
if (toxsave.isEmpty() && !isNewProfile) { if (toxsave.isEmpty() && !isNewProfile) {
qCritical() << "Existing toxsave is empty"; qCritical() << "Existing toxsave is empty";
@ -265,7 +265,7 @@ void Profile::initCore(const QByteArray& toxsave, Settings& s, bool isNewProfile
return; return;
} }
coreAv = CoreAV::makeCoreAV(core->getTox(), core->getCoreLoopLock(), s, s); coreAv = CoreAV::makeCoreAV(core->getTox(), core->getCoreLoopLock(), s, s, cameraSource);
if (!coreAv) { if (!coreAv) {
qDebug() << "Failed to start ToxAV"; qDebug() << "Failed to start ToxAV";
emit failedToStart(); emit failedToStart();
@ -311,7 +311,7 @@ Profile::Profile(const QString& name_, std::unique_ptr<ToxEncrypt> passkey_, Pat
* @note If the profile is already in use return nullptr. * @note If the profile is already in use return nullptr.
*/ */
Profile* Profile::loadProfile(const QString& name, const QString& password, Settings& settings, Profile* Profile::loadProfile(const QString& name, const QString& password, Settings& settings,
const QCommandLineParser* parser) const QCommandLineParser* parser, CameraSource& cameraSource)
{ {
if (ProfileLocker::hasLock()) { if (ProfileLocker::hasLock()) {
qCritical() << "Tried to load profile " << name << ", but another profile is already locked!"; qCritical() << "Tried to load profile " << name << ", but another profile is already locked!";
@ -339,7 +339,7 @@ Profile* Profile::loadProfile(const QString& name, const QString& password, Sett
constexpr bool isNewProfile = false; constexpr bool isNewProfile = false;
settings.updateProfileData(p, parser, isNewProfile); settings.updateProfileData(p, parser, isNewProfile);
p->initCore(toxsave, settings, isNewProfile); p->initCore(toxsave, settings, isNewProfile, cameraSource);
p->loadDatabase(password); p->loadDatabase(password);
return p; return p;
@ -354,7 +354,7 @@ Profile* Profile::loadProfile(const QString& name, const QString& password, Sett
* @note If the profile is already in use return nullptr. * @note If the profile is already in use return nullptr.
*/ */
Profile* Profile::createProfile(const QString& name, const QString& password, Settings& settings, Profile* Profile::createProfile(const QString& name, const QString& password, Settings& settings,
const QCommandLineParser* parser) const QCommandLineParser* parser, CameraSource& cameraSource)
{ {
CreateToxDataError error; CreateToxDataError error;
Paths& paths = settings.getPaths(); Paths& paths = settings.getPaths();
@ -371,7 +371,7 @@ Profile* Profile::createProfile(const QString& name, const QString& password, Se
constexpr bool isNewProfile = true; constexpr bool isNewProfile = true;
settings.updateProfileData(p, parser, isNewProfile); settings.updateProfileData(p, parser, isNewProfile);
p->initCore(QByteArray(), settings, isNewProfile); p->initCore(QByteArray(), settings, isNewProfile, cameraSource);
p->loadDatabase(password); p->loadDatabase(password);
return p; return p;
} }

View File

@ -38,6 +38,7 @@
class Settings; class Settings;
class QCommandLineParser; class QCommandLineParser;
class ToxPk; class ToxPk;
class CameraSource;
class Profile : public QObject class Profile : public QObject
{ {
@ -45,9 +46,9 @@ class Profile : public QObject
public: public:
static Profile* loadProfile(const QString& name, const QString& password, Settings& settings, static Profile* loadProfile(const QString& name, const QString& password, Settings& settings,
const QCommandLineParser* parser); const QCommandLineParser* parser, CameraSource&);
static Profile* createProfile(const QString& name, const QString& password, Settings& settings, static Profile* createProfile(const QString& name, const QString& password, Settings& settings,
const QCommandLineParser* parser); const QCommandLineParser* parser, CameraSource&);
~Profile(); ~Profile();
Core& getCore() const; Core& getCore() const;
@ -108,7 +109,7 @@ private:
static QStringList getFilesByExt(QString extension); static QStringList getFilesByExt(QString extension);
QString avatarPath(const ToxPk& owner, bool forceUnencrypted = false); QString avatarPath(const ToxPk& owner, bool forceUnencrypted = false);
bool saveToxSave(QByteArray data); bool saveToxSave(QByteArray data);
void initCore(const QByteArray& toxsave, Settings &s, bool isNewProfile); void initCore(const QByteArray& toxsave, Settings &s, bool isNewProfile, CameraSource&);
private: private:
std::unique_ptr<AvatarBroadcaster> avatarBroadcaster; std::unique_ptr<AvatarBroadcaster> avatarBroadcaster;

View File

@ -90,8 +90,6 @@ extern "C" {
* @brief Remember how many times we subscribed for RAII * @brief Remember how many times we subscribed for RAII
*/ */
CameraSource* CameraSource::instance{nullptr};
CameraSource::CameraSource() CameraSource::CameraSource()
: deviceThread{new QThread} : deviceThread{new QThread}
, deviceName{"none"} , deviceName{"none"}
@ -122,22 +120,6 @@ CameraSource::CameraSource()
// clang-format on // clang-format on
/**
* @brief Returns the singleton instance.
*/
CameraSource& CameraSource::getInstance()
{
if (!instance)
instance = new CameraSource();
return *instance;
}
void CameraSource::destroyInstance()
{
delete instance;
instance = nullptr;
}
/** /**
* @brief Setup default device * @brief Setup default device
* @note If a device is already open, the source will seamlessly switch to the new device. * @note If a device is already open, the source will seamlessly switch to the new device.

View File

@ -36,8 +36,8 @@ class CameraSource : public VideoSource
Q_OBJECT Q_OBJECT
public: public:
static CameraSource& getInstance(); CameraSource();
static void destroyInstance(); ~CameraSource();
void setupDefault(); void setupDefault();
bool isNone() const; bool isNone() const;
@ -53,8 +53,6 @@ signals:
void openFailed(); void openFailed();
private: private:
CameraSource();
~CameraSource();
void stream(); void stream();
private slots: private slots:
@ -78,6 +76,4 @@ private:
std::atomic_bool isNone_; std::atomic_bool isNone_;
std::atomic_int subscriptions; std::atomic_int subscriptions;
static CameraSource* instance;
}; };

View File

@ -47,11 +47,12 @@ const int BTN_PANEL_WIDTH = 250;
const auto BTN_STYLE_SHEET_PATH = QStringLiteral("chatForm/fullScreenButtons.css"); const auto BTN_STYLE_SHEET_PATH = QStringLiteral("chatForm/fullScreenButtons.css");
} }
NetCamView::NetCamView(ToxPk friendPk_, QWidget* parent) NetCamView::NetCamView(ToxPk friendPk_, CameraSource& cameraSource_, QWidget* parent)
: QWidget(parent) : QWidget(parent)
, selfFrame{nullptr} , selfFrame{nullptr}
, friendPk{friendPk_} , friendPk{friendPk_}
, e(false) , e(false)
, cameraSource{cameraSource_}
{ {
verLayout = new QVBoxLayout(this); verLayout = new QVBoxLayout(this);
setWindowTitle(tr("Tox video")); setWindowTitle(tr("Tox video"));
@ -167,7 +168,7 @@ NetCamView::~NetCamView()
void NetCamView::show(VideoSource* source, const QString& title) void NetCamView::show(VideoSource* source, const QString& title)
{ {
setSource(source); setSource(source);
selfVideoSurface->setSource(&CameraSource::getInstance()); selfVideoSurface->setSource(&cameraSource);
setTitle(title); setTitle(title);
QWidget::show(); QWidget::show();

View File

@ -34,13 +34,14 @@ class QPushButton;
class QKeyEvent; class QKeyEvent;
class QCloseEvent; class QCloseEvent;
class QShowEvent; class QShowEvent;
class CameraSource;
class NetCamView : public QWidget class NetCamView : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
NetCamView(ToxPk friendPk_, QWidget* parent = nullptr); NetCamView(ToxPk friendPk_, CameraSource&, QWidget* parent = nullptr);
~NetCamView(); ~NetCamView();
virtual void show(VideoSource* source, const QString& title); virtual void show(VideoSource* source, const QString& title);
@ -95,4 +96,5 @@ private:
QPushButton* microphoneButton = nullptr; QPushButton* microphoneButton = nullptr;
QPushButton* endVideoButton = nullptr; QPushButton* endVideoButton = nullptr;
QPushButton* exitFullScreenButton = nullptr; QPushButton* exitFullScreenButton = nullptr;
CameraSource& cameraSource;
}; };

View File

@ -107,13 +107,15 @@ QString secondsToDHMS(quint32 duration)
} // namespace } // namespace
ChatForm::ChatForm(Profile& profile, Friend* chatFriend, IChatLog& chatLog_, ChatForm::ChatForm(Profile& profile, Friend* chatFriend, IChatLog& chatLog_,
IMessageDispatcher& messageDispatcher_, DocumentCache& documentCache_, SmileyPack& smileyPack_) IMessageDispatcher& messageDispatcher_, DocumentCache& documentCache_,
SmileyPack& smileyPack_, CameraSource& cameraSource_)
: GenericChatForm(profile.getCore(), chatFriend, chatLog_, messageDispatcher_, : GenericChatForm(profile.getCore(), chatFriend, chatLog_, messageDispatcher_,
documentCache_, smileyPack_) documentCache_, smileyPack_)
, core{profile.getCore()} , core{profile.getCore()}
, f(chatFriend) , f(chatFriend)
, isTyping{false} , isTyping{false}
, lastCallIsVideo{false} , lastCallIsVideo{false}
, cameraSource{cameraSource_}
{ {
setName(f->getDisplayedName()); setName(f->getDisplayedName());
@ -509,7 +511,7 @@ std::unique_ptr<NetCamView> ChatForm::createNetcam()
{ {
qDebug() << "creating netcam"; qDebug() << "creating netcam";
uint32_t friendId = f->getId(); uint32_t friendId = f->getId();
std::unique_ptr<NetCamView> view = std::unique_ptr<NetCamView>(new NetCamView(f->getPublicKey(), this)); std::unique_ptr<NetCamView> view = std::unique_ptr<NetCamView>(new NetCamView(f->getPublicKey(), cameraSource, this));
CoreAV* av = core.getAv(); CoreAV* av = core.getAv();
VideoSource* source = av->getVideoSourceFromCall(friendId); VideoSource* source = av->getVideoSourceFromCall(friendId);
view->show(source, f->getDisplayedName()); view->show(source, f->getDisplayedName());

View File

@ -50,7 +50,8 @@ class ChatForm : public GenericChatForm
Q_OBJECT Q_OBJECT
public: public:
ChatForm(Profile& profile, Friend* chatFriend, IChatLog& chatLog_, ChatForm(Profile& profile, Friend* chatFriend, IChatLog& chatLog_,
IMessageDispatcher& messageDispatcher_, DocumentCache&, SmileyPack&); IMessageDispatcher& messageDispatcher_, DocumentCache&, SmileyPack&,
CameraSource&);
~ChatForm() override; ~ChatForm() override;
void setStatusMessage(const QString& newMessage); void setStatusMessage(const QString& newMessage);
@ -141,4 +142,5 @@ private:
bool isTyping; bool isTyping;
bool lastCallIsVideo; bool lastCallIsVideo;
std::unique_ptr<NetCamView> netcam; std::unique_ptr<NetCamView> netcam;
CameraSource& cameraSource;
}; };

View File

@ -42,13 +42,12 @@
#include <memory> #include <memory>
SettingsWidget::SettingsWidget(UpdateCheck* updateCheck, IAudioControl& audio, SettingsWidget::SettingsWidget(UpdateCheck* updateCheck, IAudioControl& audio,
Core* core, SmileyPack& smileyPack, Widget* parent) Core* core, SmileyPack& smileyPack, CameraSource& cameraSource, Widget* parent)
: QWidget(parent, Qt::Window) : QWidget(parent, Qt::Window)
{ {
CoreAV* coreAV = core->getAv(); CoreAV* coreAV = core->getAv();
IAudioSettings* audioSettings = &Settings::getInstance(); IAudioSettings* audioSettings = &Settings::getInstance();
IVideoSettings* videoSettings = &Settings::getInstance(); IVideoSettings* videoSettings = &Settings::getInstance();
CameraSource& camera = CameraSource::getInstance();
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
@ -65,7 +64,7 @@ SettingsWidget::SettingsWidget(UpdateCheck* updateCheck, IAudioControl& audio,
std::unique_ptr<PrivacyForm> pfrm(new PrivacyForm(core)); std::unique_ptr<PrivacyForm> pfrm(new PrivacyForm(core));
connect(pfrm.get(), &PrivacyForm::clearAllReceipts, parent, &Widget::clearAllReceipts); connect(pfrm.get(), &PrivacyForm::clearAllReceipts, parent, &Widget::clearAllReceipts);
AVForm* rawAvfrm = new AVForm(audio, coreAV, camera, audioSettings, videoSettings); AVForm* rawAvfrm = new AVForm(audio, coreAV, cameraSource, audioSettings, videoSettings);
std::unique_ptr<AVForm> avfrm(rawAvfrm); std::unique_ptr<AVForm> avfrm(rawAvfrm);
std::unique_ptr<AdvancedForm> expfrm(new AdvancedForm()); std::unique_ptr<AdvancedForm> expfrm(new AdvancedForm());
std::unique_ptr<AboutForm> abtfrm(new AboutForm(updateCheck)); std::unique_ptr<AboutForm> abtfrm(new AboutForm(updateCheck));

View File

@ -39,12 +39,13 @@ class ContentLayout;
class UpdateCheck; class UpdateCheck;
class Widget; class Widget;
class SmileyPack; class SmileyPack;
class CameraSource;
class SettingsWidget : public QWidget class SettingsWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
SettingsWidget(UpdateCheck* updateCheck, IAudioControl& audio, Core *core, SmileyPack&, Widget* parent = nullptr); SettingsWidget(UpdateCheck* updateCheck, IAudioControl& audio, Core *core, SmileyPack&, CameraSource&, Widget* parent = nullptr);
~SettingsWidget(); ~SettingsWidget();
bool isShown() const; bool isShown() const;

View File

@ -139,7 +139,8 @@ void Widget::acceptFileTransfer(const ToxFile& file, const QString& path)
Widget* Widget::instance{nullptr}; Widget* Widget::instance{nullptr};
Widget::Widget(Profile &profile_, IAudioControl& audio_, QWidget* parent) Widget::Widget(Profile &profile_, IAudioControl& audio_, CameraSource& cameraSource_,
QWidget* parent)
: QMainWindow(parent) : QMainWindow(parent)
, profile{profile_} , profile{profile_}
, trayMenu{nullptr} , trayMenu{nullptr}
@ -151,6 +152,7 @@ Widget::Widget(Profile &profile_, IAudioControl& audio_, QWidget* parent)
, settings(Settings::getInstance()) , settings(Settings::getInstance())
, smileyPack(new SmileyPack()) , smileyPack(new SmileyPack())
, documentCache(new DocumentCache(*smileyPack)) , documentCache(new DocumentCache(*smileyPack))
, cameraSource{cameraSource_}
{ {
installEventFilter(this); installEventFilter(this);
QString locale = settings.getTranslation(); QString locale = settings.getTranslation();
@ -292,7 +294,8 @@ void Widget::init()
updateCheck = std::unique_ptr<UpdateCheck>(new UpdateCheck(settings)); updateCheck = std::unique_ptr<UpdateCheck>(new UpdateCheck(settings));
connect(updateCheck.get(), &UpdateCheck::updateAvailable, this, &Widget::onUpdateAvailable); connect(updateCheck.get(), &UpdateCheck::updateAvailable, this, &Widget::onUpdateAvailable);
#endif #endif
settingsWidget = new SettingsWidget(updateCheck.get(), audio, core, *smileyPack, this); settingsWidget = new SettingsWidget(updateCheck.get(), audio, core, *smileyPack,
cameraSource, this);
#if UPDATE_CHECK_ENABLED #if UPDATE_CHECK_ENABLED
updateCheck->checkForUpdate(); updateCheck->checkForUpdate();
#endif #endif
@ -1190,7 +1193,7 @@ void Widget::addFriend(uint32_t friendId, const ToxPk& friendPk)
std::make_shared<ChatHistory>(*newfriend, history, *core, settings, std::make_shared<ChatHistory>(*newfriend, history, *core, settings,
*friendMessageDispatcher); *friendMessageDispatcher);
auto friendForm = new ChatForm(profile, newfriend, *chatHistory, auto friendForm = new ChatForm(profile, newfriend, *chatHistory,
*friendMessageDispatcher, *documentCache, *smileyPack); *friendMessageDispatcher, *documentCache, *smileyPack, cameraSource);
connect(friendForm, &ChatForm::updateFriendActivity, this, &Widget::updateFriendActivity); connect(friendForm, &ChatForm::updateFriendActivity, this, &Widget::updateFriendActivity);
friendMessageDispatchers[friendPk] = friendMessageDispatcher; friendMessageDispatchers[friendPk] = friendMessageDispatcher;

View File

@ -84,6 +84,7 @@ class Settings;
class IChatLog; class IChatLog;
class ChatHistory; class ChatHistory;
class SmileyPack; class SmileyPack;
class CameraSource;
class Widget final : public QMainWindow class Widget final : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -117,7 +118,8 @@ private:
}; };
public: public:
explicit Widget(Profile& profile_, IAudioControl& audio_, QWidget* parent = nullptr); Widget(Profile& profile_, IAudioControl& audio_, CameraSource&,
QWidget* parent = nullptr);
~Widget() override; ~Widget() override;
void init(); void init();
void setCentralWidget(QWidget* widget, const QString& widgetName); void setCentralWidget(QWidget* widget, const QString& widgetName);
@ -383,6 +385,7 @@ private:
#endif #endif
std::unique_ptr<SmileyPack> smileyPack; std::unique_ptr<SmileyPack> smileyPack;
std::unique_ptr<DocumentCache> documentCache; std::unique_ptr<DocumentCache> documentCache;
CameraSource& cameraSource;
}; };
bool toxActivateEventHandler(const QByteArray& data); bool toxActivateEventHandler(const QByteArray& data);