mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
reimplement audio in/out subscription concept
This commit is contained in:
parent
27bfade9e1
commit
0615c7c3c6
|
@ -152,6 +152,8 @@ public:
|
||||||
|
|
||||||
class AudioPrivate
|
class AudioPrivate
|
||||||
{
|
{
|
||||||
|
typedef QList<Audio::SID> ALSources;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioPrivate()
|
AudioPrivate()
|
||||||
: audioThread(new QThread)
|
: audioThread(new QThread)
|
||||||
|
@ -162,6 +164,7 @@ public:
|
||||||
, outputVolume(1.f)
|
, outputVolume(1.f)
|
||||||
, inputInitialized(false)
|
, inputInitialized(false)
|
||||||
, outputInitialized(false)
|
, outputInitialized(false)
|
||||||
|
, inSubscriptions(0)
|
||||||
{
|
{
|
||||||
audioThread->setObjectName("qTox Audio");
|
audioThread->setObjectName("qTox Audio");
|
||||||
QObject::connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
QObject::connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
||||||
|
@ -196,8 +199,8 @@ public:
|
||||||
bool inputInitialized;
|
bool inputInitialized;
|
||||||
bool outputInitialized;
|
bool outputInitialized;
|
||||||
|
|
||||||
Audio::PtrList inputSubscriptions;
|
quint32 inSubscriptions;
|
||||||
Audio::PtrList outputSubscriptions;
|
ALSources outSources;
|
||||||
|
|
||||||
QPointer<AudioMeter> audioMeter;
|
QPointer<AudioMeter> audioMeter;
|
||||||
};
|
};
|
||||||
|
@ -370,17 +373,15 @@ bool Audio::reinitOutput(const QString& outDevDesc)
|
||||||
|
|
||||||
If the input device is not open, it will be opened before capturing.
|
If the input device is not open, it will be opened before capturing.
|
||||||
*/
|
*/
|
||||||
void Audio::subscribeInput(const void* inListener)
|
void Audio::subscribeInput()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&d->audioLock);
|
QMutexLocker locker(&d->audioLock);
|
||||||
|
|
||||||
if (!d->alInDev)
|
if (!d->alInDev)
|
||||||
d->initInput(Settings::getInstance().getInDev());
|
d->initInput(Settings::getInstance().getInDev());
|
||||||
|
|
||||||
if (!d->inputSubscriptions.contains(inListener)) {
|
d->inSubscriptions++;
|
||||||
d->inputSubscriptions << inListener;
|
qDebug() << "Subscribed to audio input device [" << d->inSubscriptions << "subscriptions ]";
|
||||||
qDebug() << "Subscribed to audio input device [" << d->inputSubscriptions.size() << "subscriptions ]";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -388,47 +389,19 @@ void Audio::subscribeInput(const void* inListener)
|
||||||
|
|
||||||
If the input device has no more subscriptions, it will be closed.
|
If the input device has no more subscriptions, it will be closed.
|
||||||
*/
|
*/
|
||||||
void Audio::unsubscribeInput(const void* inListener)
|
void Audio::unsubscribeInput()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&d->audioLock);
|
QMutexLocker locker(&d->audioLock);
|
||||||
|
|
||||||
if (inListener && d->inputSubscriptions.size())
|
if (d->inSubscriptions > 0) {
|
||||||
{
|
d->inSubscriptions--;
|
||||||
d->inputSubscriptions.removeOne(inListener);
|
qDebug() << "Unsubscribed from audio input device [" << d->inSubscriptions << "subscriptions left ]";
|
||||||
qDebug() << "Unsubscribed from audio input device [" << d->inputSubscriptions.size() << "subscriptions left ]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->inputSubscriptions.isEmpty())
|
if (!d->inSubscriptions)
|
||||||
d->cleanupInput();
|
d->cleanupInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::subscribeOutput(const void* outListener)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&d->audioLock);
|
|
||||||
|
|
||||||
if (!d->alOutDev)
|
|
||||||
d->initOutput(Settings::getInstance().getOutDev());
|
|
||||||
|
|
||||||
if (!d->outputSubscriptions.contains(outListener)) {
|
|
||||||
d->outputSubscriptions << outListener;
|
|
||||||
qDebug() << "Subscribed to audio output device [" << d->outputSubscriptions.size() << "subscriptions ]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Audio::unsubscribeOutput(const void* outListener)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&d->audioLock);
|
|
||||||
|
|
||||||
if (outListener && d->outputSubscriptions.size())
|
|
||||||
{
|
|
||||||
d->outputSubscriptions.removeOne(outListener);
|
|
||||||
qDebug() << "Unsubscribed from audio output device [" << d->outputSubscriptions.size() << " subscriptions left ]";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->outputSubscriptions.isEmpty())
|
|
||||||
d->cleanupOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioPrivate::initInput(const QString& inDevDescr)
|
void AudioPrivate::initInput(const QString& inDevDescr)
|
||||||
{
|
{
|
||||||
qDebug() << "Opening audio input" << inDevDescr;
|
qDebug() << "Opening audio input" << inDevDescr;
|
||||||
|
@ -473,10 +446,6 @@ void AudioPrivate::initInput(const QString& inDevDescr)
|
||||||
else
|
else
|
||||||
qWarning() << "Cannot open input audio device" << inDevDescr;
|
qWarning() << "Cannot open input audio device" << inDevDescr;
|
||||||
|
|
||||||
Core* core = Core::getInstance();
|
|
||||||
if (core)
|
|
||||||
core->getAv()->resetCallSources(); // Force to regen each group call's sources
|
|
||||||
|
|
||||||
// Restart the capture if necessary
|
// Restart the capture if necessary
|
||||||
if (alInDev)
|
if (alInDev)
|
||||||
{
|
{
|
||||||
|
@ -500,6 +469,7 @@ Open an audio output device
|
||||||
bool AudioPrivate::initOutput(const QString& outDevDescr)
|
bool AudioPrivate::initOutput(const QString& outDevDescr)
|
||||||
{
|
{
|
||||||
qDebug() << "Opening audio output" << outDevDescr;
|
qDebug() << "Opening audio output" << outDevDescr;
|
||||||
|
outSources.clear();
|
||||||
|
|
||||||
outputInitialized = false;
|
outputInitialized = false;
|
||||||
if (outDevDescr == "none")
|
if (outDevDescr == "none")
|
||||||
|
@ -508,29 +478,29 @@ bool AudioPrivate::initOutput(const QString& outDevDescr)
|
||||||
assert(!alOutDev);
|
assert(!alOutDev);
|
||||||
|
|
||||||
if (outDevDescr.isEmpty())
|
if (outDevDescr.isEmpty())
|
||||||
|
{
|
||||||
|
// Attempt to default to the first available audio device.
|
||||||
|
const ALchar *pDeviceList;
|
||||||
|
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||||
|
pDeviceList = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||||
|
else
|
||||||
|
pDeviceList = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||||
|
if (pDeviceList)
|
||||||
{
|
{
|
||||||
// Attempt to default to the first available audio device.
|
alOutDev = alcOpenDevice(pDeviceList);
|
||||||
const ALchar *pDeviceList;
|
int len = strlen(pDeviceList);
|
||||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
#ifdef Q_OS_WIN
|
||||||
pDeviceList = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
QString outDev = QString::fromUtf8(pDeviceList, len);
|
||||||
else
|
#else
|
||||||
pDeviceList = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
QString outDev = QString::fromLocal8Bit(pDeviceList, len);
|
||||||
if (pDeviceList)
|
#endif
|
||||||
{
|
Settings::getInstance().setOutDev(outDev);
|
||||||
alOutDev = alcOpenDevice(pDeviceList);
|
|
||||||
int len = strlen(pDeviceList);
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
QString outDev = QString::fromUtf8(pDeviceList, len);
|
|
||||||
#else
|
|
||||||
QString outDev = QString::fromLocal8Bit(pDeviceList, len);
|
|
||||||
#endif
|
|
||||||
Settings::getInstance().setOutDev(outDev);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alOutDev = alcOpenDevice(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alOutDev = alcOpenDevice(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
alOutDev = alcOpenDevice(outDevDescr.toStdString().c_str());
|
alOutDev = alcOpenDevice(outDevDescr.toStdString().c_str());
|
||||||
|
|
||||||
|
@ -551,7 +521,7 @@ bool AudioPrivate::initOutput(const QString& outDevDescr)
|
||||||
|
|
||||||
Core* core = Core::getInstance();
|
Core* core = Core::getInstance();
|
||||||
if (core)
|
if (core)
|
||||||
core->getAv()->resetCallSources(); // Force to regen each group call's sources
|
core->getAv()->invalidateCallSources(); // Force to regen each group call's sources
|
||||||
|
|
||||||
outputInitialized = true;
|
outputInitialized = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -577,7 +547,7 @@ void Audio::playMono16Sound(const QByteArray& data)
|
||||||
connect(player, &AudioPlayer::finished, [=]() {
|
connect(player, &AudioPlayer::finished, [=]() {
|
||||||
QMutexLocker locker(&d->audioLock);
|
QMutexLocker locker(&d->audioLock);
|
||||||
|
|
||||||
if (d->outputSubscriptions.isEmpty())
|
if (d->outSources.isEmpty())
|
||||||
d->cleanupOutput();
|
d->cleanupOutput();
|
||||||
else
|
else
|
||||||
qDebug("Audio output not closed -> there are pending subscriptions.");
|
qDebug("Audio output not closed -> there are pending subscriptions.");
|
||||||
|
@ -648,6 +618,9 @@ void Audio::playAudioBuffer(quint32 alSource, const int16_t *data, int samples,
|
||||||
assert(channels == 1 || channels == 2);
|
assert(channels == 1 || channels == 2);
|
||||||
QMutexLocker locker(&d->audioLock);
|
QMutexLocker locker(&d->audioLock);
|
||||||
|
|
||||||
|
if (!(d->alOutDev && d->outputInitialized))
|
||||||
|
return;
|
||||||
|
|
||||||
ALuint bufid;
|
ALuint bufid;
|
||||||
ALint processed = 0, queued = 16;
|
ALint processed = 0, queued = 16;
|
||||||
alGetSourcei(alSource, AL_BUFFERS_PROCESSED, &processed);
|
alGetSourcei(alSource, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
@ -767,19 +740,41 @@ const char* Audio::inDeviceNames()
|
||||||
return alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
return alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::createSource(quint32* sid)
|
void Audio::subscribeOutput(SID& sid)
|
||||||
{
|
{
|
||||||
alGenSources(1, sid);
|
QMutexLocker locker(&d->audioLock);
|
||||||
alSourcef(*sid, AL_GAIN, 1.f);
|
|
||||||
|
if (!d->alOutDev)
|
||||||
|
d->initOutput(Settings::getInstance().getOutDev());
|
||||||
|
|
||||||
|
alGenSources(1, &sid);
|
||||||
|
assert(sid);
|
||||||
|
alSourcef(sid, AL_GAIN, 1.f);
|
||||||
|
d->outSources << sid;
|
||||||
|
qDebug() << "Audio source" << sid << "created. Sources active:"
|
||||||
|
<< d->outSources.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::deleteSource(quint32 sid)
|
void Audio::unsubscribeOutput(SID& sid)
|
||||||
{
|
{
|
||||||
if (alIsSource(sid)) {
|
QMutexLocker locker(&d->audioLock);
|
||||||
alDeleteSources(1, &sid);
|
|
||||||
} else {
|
if (sid) {
|
||||||
qWarning() << "Trying to delete invalid audio source" << sid;
|
if (alIsSource(sid)) {
|
||||||
|
alDeleteSources(1, &sid);
|
||||||
|
qDebug() << "Audio source" << sid << "deleted. Sources active:"
|
||||||
|
<< d->outSources.size();
|
||||||
|
} else {
|
||||||
|
qWarning() << "Trying to delete invalid audio source" << sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
sid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->outSources.removeAll(sid);
|
||||||
|
|
||||||
|
if (d->outSources.isEmpty())
|
||||||
|
d->cleanupOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::startLoop()
|
void Audio::startLoop()
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
#ifndef AUDIO_H
|
#ifndef AUDIO_H
|
||||||
#define AUDIO_H
|
#define AUDIO_H
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QMutexLocker>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
|
|
||||||
struct Tox;
|
struct Tox;
|
||||||
|
@ -44,7 +44,7 @@ class Audio : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef QList<const void*> PtrList;
|
typedef quint32 SID;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Audio& getInstance();
|
static Audio& getInstance();
|
||||||
|
@ -68,8 +68,8 @@ public:
|
||||||
|
|
||||||
static const char* outDeviceNames();
|
static const char* outDeviceNames();
|
||||||
static const char* inDeviceNames();
|
static const char* inDeviceNames();
|
||||||
void createSource(quint32* sid);
|
void subscribeOutput(SID& sid);
|
||||||
void deleteSource(quint32 sid);
|
void unsubscribeOutput(SID& sid);
|
||||||
|
|
||||||
void startLoop();
|
void startLoop();
|
||||||
void stopLoop();
|
void stopLoop();
|
||||||
|
@ -88,10 +88,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void subscribeInput(const void* inListener);
|
void subscribeInput();
|
||||||
void subscribeOutput(const void* outListener);
|
void unsubscribeInput();
|
||||||
void unsubscribeInput(const void* inListener);
|
|
||||||
void unsubscribeOutput(const void* outListener);
|
|
||||||
void playGroupAudio(int group, int peer, const int16_t* data,
|
void playGroupAudio(int group, int peer, const int16_t* data,
|
||||||
unsigned samples, uint8_t channels, unsigned sample_rate);
|
unsigned samples, uint8_t channels, unsigned sample_rate);
|
||||||
|
|
||||||
|
|
|
@ -470,24 +470,16 @@ bool CoreAV::isGroupAvEnabled(int groupId) const
|
||||||
return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV;
|
return tox_group_get_type(Core::getInstance()->tox, groupId) == TOX_GROUPCHAT_TYPE_AV;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::resetCallSources()
|
void CoreAV::invalidateCallSources()
|
||||||
{
|
{
|
||||||
for (ToxGroupCall& call : groupCalls)
|
for (ToxGroupCall& call : groupCalls)
|
||||||
{
|
{
|
||||||
if (call.alSource)
|
call.alSource = 0;
|
||||||
{
|
|
||||||
Audio::getInstance().deleteSource(call.alSource);
|
|
||||||
Audio::getInstance().createSource(&call.alSource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ToxFriendCall& call : calls)
|
for (ToxFriendCall& call : calls)
|
||||||
{
|
{
|
||||||
if (call.alSource)
|
call.alSource = 0;
|
||||||
{
|
|
||||||
Audio::getInstance().deleteSource(call.alSource);
|
|
||||||
Audio::getInstance().createSource(&call.alSource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,10 +638,11 @@ void CoreAV::audioFrameCallback(ToxAV *, uint32_t friendNum, const int16_t *pcm,
|
||||||
if (call.muteVol)
|
if (call.muteVol)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Audio& audio = Audio::getInstance();
|
||||||
if (!call.alSource)
|
if (!call.alSource)
|
||||||
Audio::getInstance().createSource(&call.alSource);
|
audio.subscribeOutput(call.alSource);
|
||||||
|
|
||||||
Audio::getInstance().playAudioBuffer(call.alSource, pcm, sampleCount, channels, samplingRate);
|
audio.playAudioBuffer(call.alSource, pcm, sampleCount, channels, samplingRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::videoFrameCallback(ToxAV *, uint32_t friendNum, uint16_t w, uint16_t h,
|
void CoreAV::videoFrameCallback(ToxAV *, uint32_t friendNum, uint16_t w, uint16_t h,
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
bool sendGroupCallAudio(int groupNum);
|
bool sendGroupCallAudio(int groupNum);
|
||||||
|
|
||||||
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
|
||||||
void resetCallSources(); ///< Forces to regenerate each call's audio sources
|
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.
|
void sendNoVideo(); ///< Signal to all peers that we're not sending video anymore. The next frame sent cancels this.
|
||||||
|
|
||||||
void joinGroupCall(int groupNum); ///< Starts a call in an existing AV groupchat. Call from the GUI thread.
|
void joinGroupCall(int groupNum); ///< Starts a call in an existing AV groupchat. Call from the GUI thread.
|
||||||
|
|
|
@ -21,8 +21,8 @@ ToxCall::ToxCall(uint32_t CallId)
|
||||||
sendAudioTimer->setSingleShot(true);
|
sendAudioTimer->setSingleShot(true);
|
||||||
|
|
||||||
Audio& audio = Audio::getInstance();
|
Audio& audio = Audio::getInstance();
|
||||||
audio.subscribeInput(this);
|
audio.subscribeInput();
|
||||||
audio.subscribeOutput(this);
|
audio.subscribeOutput(alSource);
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
if (Settings::getInstance().getFilterAudio())
|
if (Settings::getInstance().getFilterAudio())
|
||||||
|
@ -46,11 +46,10 @@ ToxCall::ToxCall(ToxCall&& other) noexcept
|
||||||
other.callId = numeric_limits<decltype(callId)>::max();
|
other.callId = numeric_limits<decltype(callId)>::max();
|
||||||
other.alSource = 0;
|
other.alSource = 0;
|
||||||
|
|
||||||
|
// required -> ownership of audio input is moved to new instance
|
||||||
Audio& audio = Audio::getInstance();
|
Audio& audio = Audio::getInstance();
|
||||||
audio.subscribeInput(this);
|
audio.subscribeInput();
|
||||||
audio.unsubscribeInput(&other);
|
audio.subscribeOutput(alSource);
|
||||||
audio.subscribeOutput(this);
|
|
||||||
audio.unsubscribeOutput(&other);
|
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
filterer = other.filterer;
|
filterer = other.filterer;
|
||||||
|
@ -68,11 +67,8 @@ ToxCall::~ToxCall()
|
||||||
sendAudioTimer->stop();
|
sendAudioTimer->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alSource)
|
audio.unsubscribeInput();
|
||||||
audio.deleteSource(alSource);
|
audio.unsubscribeOutput(alSource);
|
||||||
|
|
||||||
audio.unsubscribeInput(this);
|
|
||||||
audio.unsubscribeOutput(this);
|
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
if (filterer)
|
if (filterer)
|
||||||
|
@ -92,6 +88,10 @@ const ToxCall& ToxCall::operator=(ToxCall&& other) noexcept
|
||||||
alSource = other.alSource;
|
alSource = other.alSource;
|
||||||
other.alSource = 0;
|
other.alSource = 0;
|
||||||
|
|
||||||
|
// required -> ownership of audio input is moved to new instance
|
||||||
|
Audio& audio = Audio::getInstance();
|
||||||
|
audio.subscribeInput();
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
filterer = other.filterer;
|
filterer = other.filterer;
|
||||||
other.filterer = nullptr;
|
other.filterer = nullptr;
|
||||||
|
|
|
@ -29,14 +29,17 @@
|
||||||
#include "src/core/coreav.h"
|
#include "src/core/coreav.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QShowEvent>
|
||||||
|
|
||||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||||
#define ALC_ALL_DEVICES_SPECIFIER ALC_DEVICE_SPECIFIER
|
#define ALC_ALL_DEVICES_SPECIFIER ALC_DEVICE_SPECIFIER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AVForm::AVForm() :
|
AVForm::AVForm() :
|
||||||
GenericForm(QPixmap(":/img/settings/av.png")),
|
GenericForm(QPixmap(":/img/settings/av.png"))
|
||||||
camVideoSurface{nullptr}, camera(CameraSource::getInstance())
|
, subscribedToAudioIn{false}
|
||||||
|
, camVideoSurface{nullptr}
|
||||||
|
, camera(CameraSource::getInstance())
|
||||||
{
|
{
|
||||||
bodyUI = new Ui::AVSettings;
|
bodyUI = new Ui::AVSettings;
|
||||||
bodyUI->setupUi(this);
|
bodyUI->setupUi(this);
|
||||||
|
@ -90,15 +93,38 @@ AVForm::~AVForm()
|
||||||
delete bodyUI;
|
delete bodyUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVForm::showEvent(QShowEvent*)
|
void AVForm::hideEvent(QHideEvent* event)
|
||||||
|
{
|
||||||
|
if (subscribedToAudioIn) {
|
||||||
|
// TODO: this should not be done in show/hide events
|
||||||
|
Audio::getInstance().unsubscribeInput();
|
||||||
|
subscribedToAudioIn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (camVideoSurface)
|
||||||
|
{
|
||||||
|
camVideoSurface->setSource(nullptr);
|
||||||
|
killVideoSurface();
|
||||||
|
}
|
||||||
|
videoDeviceList.clear();
|
||||||
|
|
||||||
|
GenericForm::hideEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVForm::showEvent(QShowEvent* event)
|
||||||
{
|
{
|
||||||
getAudioOutDevices();
|
getAudioOutDevices();
|
||||||
getAudioInDevices();
|
getAudioInDevices();
|
||||||
createVideoSurface();
|
createVideoSurface();
|
||||||
getVideoDevices();
|
getVideoDevices();
|
||||||
Audio& audio = Audio::getInstance();
|
|
||||||
audio.subscribeInput(this);
|
if (!subscribedToAudioIn) {
|
||||||
audio.subscribeOutput(this);
|
// TODO: this should not be done in show/hide events
|
||||||
|
Audio::getInstance().subscribeInput();
|
||||||
|
subscribedToAudioIn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericForm::showEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVForm::onVideoModesIndexChanged(int index)
|
void AVForm::onVideoModesIndexChanged(int index)
|
||||||
|
@ -227,19 +253,6 @@ void AVForm::onVideoDevChanged(int index)
|
||||||
Core::getInstance()->getAv()->sendNoVideo();
|
Core::getInstance()->getAv()->sendNoVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVForm::hideEvent(QHideEvent *)
|
|
||||||
{
|
|
||||||
if (camVideoSurface)
|
|
||||||
{
|
|
||||||
camVideoSurface->setSource(nullptr);
|
|
||||||
killVideoSurface();
|
|
||||||
}
|
|
||||||
videoDeviceList.clear();
|
|
||||||
Audio& audio = Audio::getInstance();
|
|
||||||
audio.unsubscribeInput(this);
|
|
||||||
audio.unsubscribeOutput(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AVForm::getVideoDevices()
|
void AVForm::getVideoDevices()
|
||||||
{
|
{
|
||||||
QString settingsInDev = Settings::getInstance().getVideoDev();
|
QString settingsInDev = Settings::getInstance().getVideoDev();
|
||||||
|
|
|
@ -39,7 +39,7 @@ class AVForm : public GenericForm
|
||||||
public:
|
public:
|
||||||
AVForm();
|
AVForm();
|
||||||
~AVForm();
|
~AVForm();
|
||||||
virtual QString getFormName() final override {return tr("Audio/Video");}
|
QString getFormName() final override {return tr("Audio/Video");}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void getAudioInDevices();
|
void getAudioInDevices();
|
||||||
|
@ -64,15 +64,18 @@ private slots:
|
||||||
void onVideoDevChanged(int index);
|
void onVideoDevChanged(int index);
|
||||||
void onVideoModesIndexChanged(int index);
|
void onVideoModesIndexChanged(int index);
|
||||||
|
|
||||||
virtual void hideEvent(QHideEvent*) final override;
|
|
||||||
virtual void showEvent(QShowEvent*) final override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool eventFilter(QObject *o, QEvent *e) final override;
|
|
||||||
void updateVideoModes(int curIndex);
|
void updateVideoModes(int curIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool eventFilter(QObject *o, QEvent *e) final override;
|
||||||
|
|
||||||
|
void hideEvent(QHideEvent* event) final override;
|
||||||
|
void showEvent(QShowEvent*event) final override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::AVSettings *bodyUI;
|
Ui::AVSettings *bodyUI;
|
||||||
|
bool subscribedToAudioIn;
|
||||||
VideoSurface *camVideoSurface;
|
VideoSurface *camVideoSurface;
|
||||||
CameraSource &camera;
|
CameraSource &camera;
|
||||||
QVector<QPair<QString, QString>> videoDeviceList;
|
QVector<QPair<QString, QString>> videoDeviceList;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user