mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 20:55:10 +02:00
cleanup AudioInjector memory management
This commit is contained in:
parent
c5c3d24c2d
commit
7b485829c4
6 changed files with 49 additions and 73 deletions
|
@ -542,9 +542,6 @@ Application::~Application() {
|
||||||
_nodeThread->quit();
|
_nodeThread->quit();
|
||||||
_nodeThread->wait();
|
_nodeThread->wait();
|
||||||
|
|
||||||
// kill any audio injectors that are still around
|
|
||||||
AudioScriptingInterface::getInstance().stopAllInjectors();
|
|
||||||
|
|
||||||
auto audioIO = DependencyManager::get<AudioClient>();
|
auto audioIO = DependencyManager::get<AudioClient>();
|
||||||
|
|
||||||
// stop the audio process
|
// stop the audio process
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// 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/QCoreApplication>
|
||||||
#include <QtCore/QDataStream>
|
#include <QtCore/QDataStream>
|
||||||
|
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
|
@ -22,6 +23,9 @@
|
||||||
#include "AudioInjector.h"
|
#include "AudioInjector.h"
|
||||||
|
|
||||||
QScriptValue injectorToScriptValue(QScriptEngine* engine, AudioInjector* const& in) {
|
QScriptValue injectorToScriptValue(QScriptEngine* engine, AudioInjector* const& in) {
|
||||||
|
// when the script goes down we want to cleanup the injector
|
||||||
|
QObject::connect(engine, &QScriptEngine::destroyed, in, &AudioInjector::stopAndDeleteLater);
|
||||||
|
|
||||||
return engine->newQObject(in);
|
return engine->newQObject(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +240,14 @@ void AudioInjector::injectToMixer() {
|
||||||
// send two packets before the first sleep so the mixer can start playback right away
|
// send two packets before the first sleep so the mixer can start playback right away
|
||||||
|
|
||||||
if (_currentSendPosition != bytesToCopy && _currentSendPosition < _audioData.size()) {
|
if (_currentSendPosition != bytesToCopy && _currentSendPosition < _audioData.size()) {
|
||||||
|
|
||||||
|
// process events in case we have been told to stop and be deleted
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
if (_shouldStop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// not the first packet and not done
|
// not the first packet and not done
|
||||||
// sleep for the appropriate time
|
// sleep for the appropriate time
|
||||||
int usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000;
|
int usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000;
|
||||||
|
@ -264,3 +276,8 @@ void AudioInjector::stop() {
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioInjector::stopAndDeleteLater() {
|
||||||
|
stop();
|
||||||
|
QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define hifi_AudioInjector_h
|
#define hifi_AudioInjector_h
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
@ -42,6 +43,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
void injectAudio();
|
void injectAudio();
|
||||||
void stop();
|
void stop();
|
||||||
|
void stopAndDeleteLater();
|
||||||
void setOptions(AudioInjectorOptions& options);
|
void setOptions(AudioInjectorOptions& options);
|
||||||
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
|
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
|
||||||
float getLoudness();
|
float getLoudness();
|
||||||
|
|
|
@ -28,80 +28,47 @@ AudioScriptingInterface::AudioScriptingInterface() :
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioScriptingInterface::stopAllInjectors() {
|
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||||
QList<QPointer<AudioInjector> >::iterator injector = _activeInjectors.begin();
|
AudioInjector* injector = NULL;
|
||||||
while (injector != _activeInjectors.end()) {
|
QMetaObject::invokeMethod(this, "invokedPlaySound", Qt::BlockingQueuedConnection,
|
||||||
if (!injector->isNull()) {
|
Q_RETURN_ARG(AudioInjector*, injector),
|
||||||
injector->data()->stop();
|
Q_ARG(Sound*, sound), Q_ARG(const AudioInjectorOptions&, injectorOptions));
|
||||||
|
return injector;
|
||||||
while (injector->data() && !injector->data()->isFinished()) {
|
|
||||||
// wait for this injector to go down
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
injector = _activeInjectors.erase(injector);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
AudioInjector* AudioScriptingInterface::invokedPlaySound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||||
if (sound) {
|
if (sound) {
|
||||||
// stereo option isn't set from script, this comes from sound metadata or filename
|
// stereo option isn't set from script, this comes from sound metadata or filename
|
||||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
AudioInjectorOptions optionsCopy = injectorOptions;
|
||||||
optionsCopy.stereo = sound->isStereo();
|
optionsCopy.stereo = sound->isStereo();
|
||||||
|
|
||||||
AudioInjector* injector = new AudioInjector(sound, optionsCopy);
|
|
||||||
injector->setLocalAudioInterface(_localAudioInterface);
|
|
||||||
|
|
||||||
QThread* injectorThread = new QThread();
|
QThread* injectorThread = new QThread();
|
||||||
injectorThread->setObjectName("Audio Injector Thread");
|
injectorThread->setObjectName("Audio Injector Thread");
|
||||||
|
|
||||||
|
AudioInjector* injector = new AudioInjector(sound, optionsCopy);
|
||||||
|
injector->setLocalAudioInterface(_localAudioInterface);
|
||||||
|
|
||||||
injector->moveToThread(injectorThread);
|
injector->moveToThread(injectorThread);
|
||||||
|
|
||||||
// start injecting when the injector thread starts
|
// start injecting when the injector thread starts
|
||||||
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
||||||
|
|
||||||
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
|
||||||
connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater);
|
// connect the right slots and signals for AudioInjector and thread cleanup
|
||||||
connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
|
connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit);
|
||||||
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
|
|
||||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||||
|
connect(injectorThread, &QThread::destroyed, this, &AudioScriptingInterface::threadDead);
|
||||||
|
|
||||||
injectorThread->start();
|
injectorThread->start();
|
||||||
|
|
||||||
_activeInjectors.append(QPointer<AudioInjector>(injector));
|
|
||||||
|
|
||||||
return injector;
|
return injector;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "AudioScriptingInterface::playSound called with null Sound object.";
|
qDebug() << "AudioScriptingInterface::playSound called with null Sound object.";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioScriptingInterface::stopInjector(AudioInjector* injector) {
|
void AudioScriptingInterface::threadDead() {
|
||||||
if (injector) {
|
qDebug() << "The audio thread has gone down";
|
||||||
injector->stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) {
|
|
||||||
return (injector != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioScriptingInterface::setInjectorOptions(AudioInjector* injector, const AudioInjectorOptions& injectorOptions) {
|
|
||||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
|
||||||
if (injector) {
|
|
||||||
injector->setOptions(optionsCopy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float AudioScriptingInterface::getLoudness(AudioInjector* injector) {
|
|
||||||
if (injector) {
|
|
||||||
return injector->getLoudness();
|
|
||||||
} else {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioScriptingInterface::injectorStopped() {
|
|
||||||
_activeInjectors.removeAll(QPointer<AudioInjector>(reinterpret_cast<AudioInjector*>(sender())));
|
|
||||||
}
|
}
|
|
@ -12,40 +12,33 @@
|
||||||
#ifndef hifi_AudioScriptingInterface_h
|
#ifndef hifi_AudioScriptingInterface_h
|
||||||
#define hifi_AudioScriptingInterface_h
|
#define hifi_AudioScriptingInterface_h
|
||||||
|
|
||||||
#include <qpointer.h>
|
#include <AbstractAudioInterface.h>
|
||||||
|
#include <AudioInjector.h>
|
||||||
#include "AbstractAudioInterface.h"
|
#include <Sound.h>
|
||||||
#include "AudioInjector.h"
|
|
||||||
#include "Sound.h"
|
|
||||||
|
|
||||||
class AudioScriptingInterface : public QObject {
|
class AudioScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static AudioScriptingInterface& getInstance();
|
static AudioScriptingInterface& getInstance();
|
||||||
|
|
||||||
void stopAllInjectors();
|
|
||||||
|
|
||||||
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; }
|
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; }
|
||||||
public slots:
|
|
||||||
|
|
||||||
static float getLoudness(AudioInjector* injector);
|
|
||||||
|
|
||||||
AudioInjector* playSound(Sound* sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions());
|
|
||||||
|
|
||||||
void stopInjector(AudioInjector* injector);
|
protected:
|
||||||
bool isInjectorPlaying(AudioInjector* injector);
|
// this method is protected to stop C++ callers from calling, but invokable from script
|
||||||
|
Q_INVOKABLE AudioInjector* playSound(Sound* sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions());
|
||||||
void setInjectorOptions(AudioInjector* injector, const AudioInjectorOptions& injectorOptions);
|
|
||||||
|
|
||||||
void injectorStopped();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void mutedByMixer();
|
void mutedByMixer();
|
||||||
void environmentMuted();
|
void environmentMuted();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void threadDead();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
AudioInjector* invokedPlaySound(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioScriptingInterface();
|
AudioScriptingInterface();
|
||||||
QList< QPointer<AudioInjector> > _activeInjectors;
|
|
||||||
AbstractAudioInterface* _localAudioInterface;
|
AbstractAudioInterface* _localAudioInterface;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
#include <AnimationCache.h>
|
#include <AnimationCache.h>
|
||||||
#include <AudioScriptingInterface.h>
|
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <AvatarHashMap.h>
|
#include <AvatarHashMap.h>
|
||||||
#include <LimitedNodeList.h>
|
#include <LimitedNodeList.h>
|
||||||
|
|
||||||
#include "AbstractControllerScriptingInterface.h"
|
#include "AbstractControllerScriptingInterface.h"
|
||||||
#include "ArrayBufferClass.h"
|
#include "ArrayBufferClass.h"
|
||||||
|
#include "AudioScriptingInterface.h"
|
||||||
#include "Quat.h"
|
#include "Quat.h"
|
||||||
#include "ScriptUUID.h"
|
#include "ScriptUUID.h"
|
||||||
#include "Vec3.h"
|
#include "Vec3.h"
|
||||||
|
|
Loading…
Reference in a new issue