mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
Merge pull request #4279 from birarda/android
fix cleanup of AudioClient, avoid gvr-interface crash on OS X
This commit is contained in:
commit
5113258d72
12 changed files with 52 additions and 40 deletions
|
@ -9,8 +9,6 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
#include <AddressManager.h>
|
#include <AddressManager.h>
|
||||||
#include <HifiSockAddr.h>
|
#include <HifiSockAddr.h>
|
||||||
|
|
|
@ -16,13 +16,14 @@
|
||||||
|
|
||||||
#include <HifiSockAddr.h>
|
#include <HifiSockAddr.h>
|
||||||
|
|
||||||
class QThread;
|
|
||||||
|
|
||||||
class Client : public QObject {
|
class Client : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Client(QObject* parent = 0);
|
Client(QObject* parent = 0);
|
||||||
|
|
||||||
|
virtual void cleanupBeforeQuit() = 0;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void setupNetworking();
|
void setupNetworking();
|
||||||
virtual void processVerifiedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& incomingPacket);
|
virtual void processVerifiedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& incomingPacket);
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -86,6 +86,13 @@ GVRInterface::GVRInterface(int argc, char* argv[]) :
|
||||||
QTimer* idleTimer = new QTimer(this);
|
QTimer* idleTimer = new QTimer(this);
|
||||||
connect(idleTimer, &QTimer::timeout, this, &GVRInterface::idle);
|
connect(idleTimer, &QTimer::timeout, this, &GVRInterface::idle);
|
||||||
idleTimer->start(0);
|
idleTimer->start(0);
|
||||||
|
|
||||||
|
// call our quit handler before we go down
|
||||||
|
connect(this, &QCoreApplication::aboutToQuit, this, &GVRInterface::handleApplicationQuit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GVRInterface::handleApplicationQuit() {
|
||||||
|
_client->cleanupBeforeQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GVRInterface::idle() {
|
void GVRInterface::idle() {
|
||||||
|
|
|
@ -53,6 +53,7 @@ private slots:
|
||||||
void handleApplicationStateChange(Qt::ApplicationState state);
|
void handleApplicationStateChange(Qt::ApplicationState state);
|
||||||
void idle();
|
void idle();
|
||||||
private:
|
private:
|
||||||
|
void handleApplicationQuit();
|
||||||
|
|
||||||
void enterVRMode();
|
void enterVRMode();
|
||||||
void leaveVRMode();
|
void leaveVRMode();
|
||||||
|
|
|
@ -37,7 +37,7 @@ RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString
|
||||||
DependencyManager::set<AvatarHashMap>();
|
DependencyManager::set<AvatarHashMap>();
|
||||||
|
|
||||||
// get our audio client setup on its own thread
|
// get our audio client setup on its own thread
|
||||||
QThread* audioThread = new QThread(this);
|
QThread* audioThread = new QThread();
|
||||||
auto audioClient = DependencyManager::set<AudioClient>();
|
auto audioClient = DependencyManager::set<AudioClient>();
|
||||||
|
|
||||||
audioClient->setPositionGetter(getPositionForAudio);
|
audioClient->setPositionGetter(getPositionForAudio);
|
||||||
|
@ -45,6 +45,8 @@ RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString
|
||||||
|
|
||||||
audioClient->moveToThread(audioThread);
|
audioClient->moveToThread(audioThread);
|
||||||
connect(audioThread, &QThread::started, audioClient.data(), &AudioClient::start);
|
connect(audioThread, &QThread::started, audioClient.data(), &AudioClient::start);
|
||||||
|
connect(audioClient.data(), &AudioClient::destroyed, audioThread, &QThread::quit);
|
||||||
|
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
||||||
|
|
||||||
audioThread->start();
|
audioThread->start();
|
||||||
|
|
||||||
|
@ -68,15 +70,13 @@ void RenderingClient::sendAvatarPacket() {
|
||||||
_fakeAvatar.sendIdentityPacket();
|
_fakeAvatar.sendIdentityPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderingClient::~RenderingClient() {
|
void RenderingClient::cleanupBeforeQuit() {
|
||||||
auto audioClient = DependencyManager::get<AudioClient>();
|
|
||||||
|
|
||||||
// stop the audio client
|
|
||||||
QMetaObject::invokeMethod(audioClient.data(), "stop", Qt::BlockingQueuedConnection);
|
|
||||||
|
|
||||||
// ask the audio thread to quit and wait until it is done
|
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||||
audioClient->thread()->quit();
|
"stop", Qt::BlockingQueuedConnection);
|
||||||
audioClient->thread()->wait();
|
|
||||||
|
// destroy the AudioClient so it and its thread will safely go down
|
||||||
|
DependencyManager::destroy<AudioClient>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingClient::processVerifiedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& incomingPacket) {
|
void RenderingClient::processVerifiedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& incomingPacket) {
|
||||||
|
|
|
@ -26,7 +26,6 @@ class RenderingClient : public Client {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
RenderingClient(QObject* parent = 0, const QString& launchURLString = QString());
|
RenderingClient(QObject* parent = 0, const QString& launchURLString = QString());
|
||||||
~RenderingClient();
|
|
||||||
|
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
const glm::quat& getOrientation() const { return _orientation; }
|
const glm::quat& getOrientation() const { return _orientation; }
|
||||||
|
@ -35,6 +34,8 @@ public:
|
||||||
static glm::vec3 getPositionForAudio() { return _instance->getPosition(); }
|
static glm::vec3 getPositionForAudio() { return _instance->getPosition(); }
|
||||||
static glm::quat getOrientationForAudio() { return _instance->getOrientation(); }
|
static glm::quat getOrientationForAudio() { return _instance->getOrientation(); }
|
||||||
|
|
||||||
|
virtual void cleanupBeforeQuit();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void goToLocation(const glm::vec3& newPosition,
|
void goToLocation(const glm::vec3& newPosition,
|
||||||
bool hasOrientationChange, const glm::quat& newOrientation,
|
bool hasOrientationChange, const glm::quat& newOrientation,
|
||||||
|
|
|
@ -328,7 +328,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), &_datagramProcessor, SLOT(processDatagrams()));
|
connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), &_datagramProcessor, SLOT(processDatagrams()));
|
||||||
|
|
||||||
// put the audio processing on a separate thread
|
// put the audio processing on a separate thread
|
||||||
QThread* audioThread = new QThread(this);
|
QThread* audioThread = new QThread();
|
||||||
audioThread->setObjectName("Audio Thread");
|
audioThread->setObjectName("Audio Thread");
|
||||||
|
|
||||||
auto audioIO = DependencyManager::get<AudioClient>();
|
auto audioIO = DependencyManager::get<AudioClient>();
|
||||||
|
@ -338,7 +338,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
|
|
||||||
audioIO->moveToThread(audioThread);
|
audioIO->moveToThread(audioThread);
|
||||||
connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start);
|
connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start);
|
||||||
connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
|
connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit);
|
||||||
|
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
||||||
|
connect(audioIO.data(), &AudioClient::muteToggled, this, &Application::audioMuteToggled);
|
||||||
|
|
||||||
audioThread->start();
|
audioThread->start();
|
||||||
|
|
||||||
|
@ -516,21 +518,33 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
|
|
||||||
void Application::aboutToQuit() {
|
void Application::aboutToQuit() {
|
||||||
_aboutToQuit = true;
|
_aboutToQuit = true;
|
||||||
|
|
||||||
|
cleanupBeforeQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
void Application::cleanupBeforeQuit() {
|
||||||
QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
|
||||||
_settingsThread.quit();
|
_settingsThread.quit();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
|
||||||
|
// TODO: now that this is in cleanupBeforeQuit do we really need it to stop and force
|
||||||
|
// an event loop to send the packet?
|
||||||
|
UserActivityLogger::getInstance().close();
|
||||||
|
|
||||||
|
// stop the AudioClient
|
||||||
|
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||||
|
"stop", Qt::BlockingQueuedConnection);
|
||||||
|
|
||||||
|
// destroy the AudioClient so it and its thread have a chance to go down safely
|
||||||
|
DependencyManager::destroy<AudioClient>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Application::~Application() {
|
||||||
_entities.getTree()->setSimulation(NULL);
|
_entities.getTree()->setSimulation(NULL);
|
||||||
qInstallMessageHandler(NULL);
|
qInstallMessageHandler(NULL);
|
||||||
|
|
||||||
_window->saveGeometry();
|
_window->saveGeometry();
|
||||||
|
|
||||||
int DELAY_TIME = 1000;
|
|
||||||
UserActivityLogger::getInstance().close(DELAY_TIME);
|
|
||||||
|
|
||||||
// make sure we don't call the idle timer any more
|
// make sure we don't call the idle timer any more
|
||||||
delete idleTimer;
|
delete idleTimer;
|
||||||
|
|
||||||
|
@ -541,15 +555,6 @@ Application::~Application() {
|
||||||
_nodeThread->quit();
|
_nodeThread->quit();
|
||||||
_nodeThread->wait();
|
_nodeThread->wait();
|
||||||
|
|
||||||
auto audioIO = DependencyManager::get<AudioClient>();
|
|
||||||
|
|
||||||
// stop the audio process
|
|
||||||
QMetaObject::invokeMethod(audioIO.data(), "stop", Qt::BlockingQueuedConnection);
|
|
||||||
|
|
||||||
// ask the audio thread to quit and wait until it is done
|
|
||||||
audioIO->thread()->quit();
|
|
||||||
audioIO->thread()->wait();
|
|
||||||
|
|
||||||
_octreeProcessor.terminate();
|
_octreeProcessor.terminate();
|
||||||
_entityEditSender.terminate();
|
_entityEditSender.terminate();
|
||||||
|
|
||||||
|
|
|
@ -410,6 +410,8 @@ private:
|
||||||
|
|
||||||
void initDisplay();
|
void initDisplay();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
void cleanupBeforeQuit();
|
||||||
|
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,8 @@ AudioClient::AudioClient() :
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioClient::~AudioClient() {
|
AudioClient::~AudioClient() {
|
||||||
|
stop();
|
||||||
|
|
||||||
if (_gverbLocal) {
|
if (_gverbLocal) {
|
||||||
gverb_free(_gverbLocal);
|
gverb_free(_gverbLocal);
|
||||||
}
|
}
|
||||||
|
@ -489,7 +491,6 @@ void AudioClient::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClient::stop() {
|
void AudioClient::stop() {
|
||||||
|
|
||||||
_inputFrameBuffer.finalize();
|
_inputFrameBuffer.finalize();
|
||||||
_inputGain.finalize();
|
_inputGain.finalize();
|
||||||
_sourceGain.finalize();
|
_sourceGain.finalize();
|
||||||
|
|
|
@ -188,6 +188,10 @@ protected:
|
||||||
AudioClient();
|
AudioClient();
|
||||||
~AudioClient();
|
~AudioClient();
|
||||||
|
|
||||||
|
virtual void customDeleter() {
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void outputFormatChanged();
|
void outputFormatChanged();
|
||||||
|
|
||||||
|
|
|
@ -86,17 +86,9 @@ void UserActivityLogger::launch(QString applicationVersion) {
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserActivityLogger::close(int delayTime) {
|
void UserActivityLogger::close() {
|
||||||
const QString ACTION_NAME = "close";
|
const QString ACTION_NAME = "close";
|
||||||
|
|
||||||
// In order to get the end of the session, we need to give the account manager enough time to send the packet.
|
|
||||||
QEventLoop loop;
|
|
||||||
QTimer timer;
|
|
||||||
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
|
|
||||||
// Now we can log it
|
|
||||||
logAction(ACTION_NAME, QJsonObject());
|
logAction(ACTION_NAME, QJsonObject());
|
||||||
timer.start(delayTime);
|
|
||||||
loop.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserActivityLogger::changedDisplayName(QString displayName) {
|
void UserActivityLogger::changedDisplayName(QString displayName) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ public slots:
|
||||||
void logAction(QString action, QJsonObject details = QJsonObject(), JSONCallbackParameters params = JSONCallbackParameters());
|
void logAction(QString action, QJsonObject details = QJsonObject(), JSONCallbackParameters params = JSONCallbackParameters());
|
||||||
|
|
||||||
void launch(QString applicationVersion);
|
void launch(QString applicationVersion);
|
||||||
void close(int delayTime);
|
void close();
|
||||||
void changedDisplayName(QString displayName);
|
void changedDisplayName(QString displayName);
|
||||||
void changedModel(QString typeOfModel, QString modelURL);
|
void changedModel(QString typeOfModel, QString modelURL);
|
||||||
void changedDomain(QString domainURL);
|
void changedDomain(QString domainURL);
|
||||||
|
|
Loading…
Reference in a new issue