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

the big code cleanup

* Get rid of static vars and methods and move mutexes to right places.
* Use static wrappers for the moment to retain compatibility.
This commit is contained in:
Nils Fenner 2015-10-18 15:23:33 +02:00
parent 2a2cba3cf2
commit 1c205b7c16
No known key found for this signature in database
GPG Key ID: 9591A163FF9BE04C
2 changed files with 162 additions and 58 deletions

View File

@ -31,63 +31,78 @@
#include "src/persistence/settings.h"
#include <QDebug>
#include <QThread>
#include <QMutexLocker>
#include <QTimer>
#include <QThread>
#include <cassert>
std::atomic<int> Audio::userCount{0};
Audio* Audio::instance{nullptr};
QThread* Audio::audioThread{nullptr};
QMutex* Audio::audioInLock{nullptr};
QMutex* Audio::audioOutLock{nullptr};
ALCdevice* Audio::alInDev{nullptr};
ALCdevice* Audio::alOutDev{nullptr};
ALCcontext* Audio::alContext{nullptr};
ALuint Audio::alMainSource{0};
float Audio::outputVolume{1.0};
float Audio::inputVolume{1.0};
QTimer* Audio::timer{nullptr};
Audio& Audio::getInstance()
{
if (!instance)
{
instance = new Audio();
audioThread = new QThread(instance);
audioThread->setObjectName("qTox Audio");
audioThread->start();
audioInLock = new QMutex(QMutex::Recursive);
audioOutLock = new QMutex(QMutex::Recursive);
instance->moveToThread(audioThread);
timer = new QTimer(instance);
timer->moveToThread(audioThread);
timer->setSingleShot(true);
instance->connect(timer, &QTimer::timeout, instance, &Audio::closeOutput);
instance->startAudioThread();
}
return *instance;
}
Audio::Audio()
: audioThread(new QThread())
, audioInLock(QMutex::Recursive)
, audioOutLock(QMutex::Recursive)
, userCount(0)
, alOutDev(nullptr)
, alInDev(nullptr)
, outputVolume(1.0)
, inputVolume(1.0)
, alMainSource(0)
, alContext(nullptr)
, timer(new QTimer(this))
{
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, this, &Audio::closeOutput);
audioThread->setObjectName("qTox Audio");
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
}
Audio::~Audio()
{
audioThread->exit(0);
audioThread->exit();
audioThread->wait();
if (audioThread->isRunning())
audioThread->terminate();
}
delete audioThread;
delete audioInLock;
delete audioOutLock;
void Audio::startAudioThread()
{
if (!audioThread->isRunning())
audioThread->start();
moveToThread(audioThread);
}
float Audio::getOutputVolume()
{
return getInstance().GetOutputVolume();
}
qreal Audio::GetOutputVolume()
{
QMutexLocker locker(&audioOutLock);
return outputVolume;
}
void Audio::setOutputVolume(float volume)
{
getInstance().SetOutputVolume(volume);
}
void Audio::SetOutputVolume(qreal volume)
{
QMutexLocker locker(&audioOutLock);
outputVolume = volume;
alSourcef(alMainSource, AL_GAIN, outputVolume);
@ -109,21 +124,30 @@ void Audio::setOutputVolume(float volume)
void Audio::setInputVolume(float volume)
{
getInstance().SetInputVolume(volume);
}
void Audio::SetInputVolume(qreal volume)
{
QMutexLocker locker(&audioInLock);
inputVolume = volume;
}
void Audio::suscribeInput()
{
Audio& inst = Audio::getInstance();
inst.SubscribeInput();
}
QMutexLocker lock(audioInLock);
QMutexLocker locker(audioOutLock);
void Audio::SubscribeInput()
{
assert(userCount >= 0);
qDebug() << "subscribing input";
if (!userCount++)
{
openInput(Settings::getInstance().getInDev());
OpenInput(Settings::getInstance().getInDev());
#if (!FIX_SND_PCM_PREPARE_BUG)
if (alInDev)
@ -134,16 +158,20 @@ void Audio::suscribeInput()
#endif
}
QTimer::singleShot(1, []()
QTimer::singleShot(1, [=]()
{
Audio::openOutput(Settings::getInstance().getOutDev());
OpenOutput(Settings::getInstance().getOutDev());
});
}
void Audio::unsuscribeInput()
{
QMutexLocker lock(audioInLock);
QMutexLocker locker(audioOutLock);
Audio& inst = Audio::getInstance();
inst.UnSubscribeInput();
}
void Audio::UnSubscribeInput()
{
assert(userCount > 0);
qDebug() << "unsubscribing input" << userCount;
@ -163,7 +191,12 @@ void Audio::unsuscribeInput()
void Audio::openInput(const QString& inDevDescr)
{
QMutexLocker lock(audioInLock);
getInstance().OpenInput(inDevDescr);
}
void Audio::OpenInput(const QString& inDevDescr)
{
QMutexLocker lock(&audioInLock);
auto* tmp = alInDev;
alInDev = nullptr;
if (tmp)
@ -198,12 +231,16 @@ void Audio::openInput(const QString& inDevDescr)
alcCaptureStart(alInDev);
#endif
}
}
bool Audio::openOutput(const QString& outDevDescr)
{
QMutexLocker lock(audioOutLock);
return getInstance().OpenOutput(outDevDescr);
}
bool Audio::OpenOutput(const QString &outDevDescr)
{
QMutexLocker lock(&audioOutLock);
auto* tmp = alOutDev;
alOutDev = nullptr;
if (outDevDescr.isEmpty())
@ -224,7 +261,7 @@ bool Audio::openOutput(const QString& outDevDescr)
if (tmp)
alcCloseDevice(tmp);
alContext=alcCreateContext(alOutDev,nullptr);
alContext = alcCreateContext(alOutDev,nullptr);
if (!alcMakeContextCurrent(alContext))
{
qWarning() << "Cannot create output audio context";
@ -247,9 +284,14 @@ bool Audio::openOutput(const QString& outDevDescr)
}
void Audio::closeInput()
{
getInstance().CloseInput();
}
void Audio::CloseInput()
{
qDebug() << "Closing input";
QMutexLocker lock(audioInLock);
QMutexLocker locker(&audioInLock);
if (alInDev)
{
if (alcCaptureCloseDevice(alInDev) == ALC_TRUE)
@ -265,9 +307,14 @@ void Audio::closeInput()
}
void Audio::closeOutput()
{
getInstance().CloseOutput();
}
void Audio::CloseOutput()
{
qDebug() << "Closing output";
QMutexLocker lock(audioOutLock);
QMutexLocker locker(&audioOutLock);
if (userCount > 0)
return;
@ -289,7 +336,12 @@ void Audio::closeOutput()
void Audio::playMono16Sound(const QByteArray& data)
{
QMutexLocker lock(audioOutLock);
getInstance().PlayMono16Sound(data);
}
void Audio::PlayMono16Sound(const QByteArray& data)
{
QMutexLocker lock(&audioOutLock);
if (!alOutDev)
{
@ -336,10 +388,16 @@ void Audio::playGroupAudioQueued(Tox*,int group, int peer, const int16_t* data,
void Audio::playGroupAudio(int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate)
{
getInstance().PlayGroupAudio(group, peer, data, samples, channels, sample_rate);
}
void Audio::PlayGroupAudio(int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate)
{
assert(QThread::currentThread() == audioThread);
QMutexLocker lock(audioOutLock);
QMutexLocker lock(&audioOutLock);
ToxGroupCall& call = Core::groupCalls[group];
@ -366,7 +424,7 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, u
{
assert(channels == 1 || channels == 2);
QMutexLocker lock(audioOutLock);
QMutexLocker lock(&audioOutLock);
ALuint bufid;
ALint processed = 0, queued = 16;
@ -404,17 +462,34 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, u
bool Audio::isInputReady()
{
return getInstance().IsInputReady();
}
bool Audio::IsInputReady()
{
QMutexLocker locker(&audioInLock);
return (alInDev && userCount);
}
bool Audio::isOutputClosed()
{
return getInstance().IsOutputClosed();
}
bool Audio::IsOutputClosed()
{
QMutexLocker locker(&audioOutLock);
return (alOutDev);
}
bool Audio::tryCaptureSamples(uint8_t* buf, int framesize)
{
QMutexLocker lock(audioInLock);
return getInstance().TryCaptureSamples(buf, framesize);
}
bool Audio::TryCaptureSamples(uint8_t* buf, int framesize)
{
QMutexLocker lock(&audioInLock);
ALint samples=0;
alcGetIntegerv(Audio::alInDev, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples);
@ -445,7 +520,12 @@ bool Audio::tryCaptureSamples(uint8_t* buf, int framesize)
void Audio::pauseOutput()
{
QMutexLocker lock(audioOutLock);
getInstance().PauseOutput();
}
void Audio::PauseOutput()
{
QMutexLocker lock(&audioOutLock);
qDebug() << "Pause";
if (userCount == 0)

View File

@ -23,6 +23,7 @@
#include <QObject>
#include <QHash>
#include <QMutexLocker>
#include <atomic>
#if defined(__APPLE__) && defined(__MACH__)
@ -48,29 +49,47 @@ class Audio : public QObject
public:
static Audio& getInstance(); ///< Returns the singleton's instance. Will construct on first call.
public:
void startAudioThread();
static float getOutputVolume(); ///< Returns the current output volume, between 0 and 1
qreal GetOutputVolume();
static void setOutputVolume(float volume); ///< The volume must be between 0 and 1
void SetOutputVolume(qreal volume);
static void setInputVolume(float volume); ///< The volume must be between 0 and 2
void SetInputVolume(qreal volume);
static void suscribeInput(); ///< Call when you need to capture sound from the open input device.
void SubscribeInput();
static void unsuscribeInput(); ///< Call once you don't need to capture on the open input device anymore.
void UnSubscribeInput();
static void openInput(const QString& inDevDescr); ///< Open an input device, use before suscribing
void OpenInput(const QString& inDevDescr);
static bool openOutput(const QString& outDevDescr); ///< Open an output device
static void closeInput(); ///< Close an input device, please don't use unless everyone's unsuscribed
bool OpenOutput(const QString& outDevDescr);
static void closeInput();
void CloseInput();
static void closeOutput(); ///< Close an output device
void CloseOutput();
static bool isInputReady(); ///< Returns true if the input device is open and suscribed to
bool IsInputReady();
static bool isOutputClosed(); ///< Returns true if the output device is open
bool IsOutputClosed();
static void playMono16Sound(const QByteArray& data); ///< Play a 44100Hz mono 16bit PCM sound
void PlayMono16Sound(const QByteArray& data);
static bool tryCaptureSamples(uint8_t* buf, int framesize); ///< Does nothing and return false on failure
bool TryCaptureSamples(uint8_t* buf, int framesize);
/// May be called from any thread, will always queue a call to playGroupAudio
/// The first and last argument are ignored, but allow direct compatibility with toxcore
static void playGroupAudioQueued(Tox*, int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate, void*);
void PlayGroupAudio(int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate);
#ifdef QTOX_FILTER_AUDIO
static void getEchoesToFilter(AudioFilterer* filter, int framesize);
@ -82,26 +101,31 @@ public slots:
void playGroupAudio(int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate);
static void pauseOutput();
void PauseOutput();
signals:
void groupAudioPlayed(int group, int peer, unsigned short volume);
private:
explicit Audio()=default;
Audio();
~Audio();
static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate);
void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate);
private:
static Audio* instance;
static std::atomic<int> userCount;
static ALCdevice* alOutDev, *alInDev;
static QMutex* audioInLock, *audioOutLock;
static float outputVolume;
static float inputVolume;
static ALuint alMainSource;
static QThread* audioThread;
static ALCcontext* alContext;
static QTimer* timer;
QThread* audioThread;
QMutex audioInLock;
QMutex audioOutLock;
std::atomic<int> userCount;
ALCdevice* alOutDev;
ALCdevice* alInDev;
qreal outputVolume;
qreal inputVolume;
ALuint alMainSource;
ALCcontext* alContext;
QTimer* timer;
};
#endif // AUDIO_H