mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 15:59:57 +02:00
avoid Qt QTimer thread bug by putting SoundCache on same thread
This commit is contained in:
parent
a771f72ed2
commit
e10d132f75
11 changed files with 74 additions and 61 deletions
|
@ -67,7 +67,7 @@ function maybePlaySound(deltaTime) {
|
|||
lifetime: 10
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
playing.push({ audioId: Audio.playSound(birds[whichBird].sound, options), entityId: entityId, lightId: lightId, color: birds[whichBird].color });
|
||||
}
|
||||
if (playing.length != numPlaying) {
|
||||
|
@ -159,8 +159,9 @@ function loadBirds() {
|
|||
var SOUND_BASE_URL = "http://public.highfidelity.io/sounds/Animals/";
|
||||
|
||||
for (var i = 0; i < sound_filenames.length; i++) {
|
||||
birds.push({ sound: new Sound(SOUND_BASE_URL + sound_filenames[i]),
|
||||
color: colors[i]
|
||||
} );
|
||||
birds.push({
|
||||
sound: SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]),
|
||||
color: colors[i]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -65,6 +65,7 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <SoundCache.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <UUID.h>
|
||||
|
||||
|
@ -3916,6 +3917,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);
|
||||
scriptEngine->registerGlobalObject("SoundCache", &SoundCache::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector);
|
||||
scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels);
|
||||
|
|
|
@ -43,28 +43,32 @@ void AudioScriptingInterface::stopAllInjectors() {
|
|||
}
|
||||
|
||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||
|
||||
AudioInjector* injector = new AudioInjector(sound, injectorOptions);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
||||
injector->moveToThread(injectorThread);
|
||||
|
||||
// start injecting when the injector thread starts
|
||||
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(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
|
||||
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
|
||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||
|
||||
injectorThread->start();
|
||||
|
||||
_activeInjectors.append(QPointer<AudioInjector>(injector));
|
||||
|
||||
return injector;
|
||||
if (sound) {
|
||||
AudioInjector* injector = new AudioInjector(sound, injectorOptions);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
||||
injector->moveToThread(injectorThread);
|
||||
|
||||
// start injecting when the injector thread starts
|
||||
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(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
|
||||
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
|
||||
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||
|
||||
injectorThread->start();
|
||||
|
||||
_activeInjectors.append(QPointer<AudioInjector>(injector));
|
||||
|
||||
return injector;
|
||||
} else {
|
||||
qDebug() << "AudioScriptingInterface::playSound called with null Sound object.";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioScriptingInterface::stopInjector(AudioInjector* injector) {
|
||||
|
|
|
@ -29,18 +29,19 @@
|
|||
#include "AudioEditBuffer.h"
|
||||
#include "Sound.h"
|
||||
|
||||
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, Sound* const& in) {
|
||||
return engine->newQObject(in);
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in) {
|
||||
return engine->newQObject(in.data());
|
||||
}
|
||||
|
||||
void soundFromScriptValue(const QScriptValue& object, Sound*& out) {
|
||||
out = qobject_cast<Sound*>(object.toQObject());
|
||||
void soundFromScriptValue(const QScriptValue &object, SharedSoundPointer &out) {
|
||||
out = SharedSoundPointer(qobject_cast<Sound*>(object.toQObject()));
|
||||
qDebug() << "Sound from script value" << out.data();
|
||||
}
|
||||
|
||||
Sound::Sound(const QUrl& url, bool isStereo) :
|
||||
Resource(url),
|
||||
_isStereo(isStereo)
|
||||
_isStereo(isStereo),
|
||||
_isReady(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -70,6 +71,8 @@ void Sound::downloadFinished(QNetworkReply* reply) {
|
|||
} else {
|
||||
qDebug() << "Network reply without 'Content-Type'.";
|
||||
}
|
||||
|
||||
_isReady = true;
|
||||
}
|
||||
|
||||
void Sound::downSample(const QByteArray& rawAudioByteArray) {
|
||||
|
|
|
@ -21,17 +21,19 @@
|
|||
class Sound : public Resource {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool downloaded READ isLoaded)
|
||||
Q_PROPERTY(bool downloaded READ isReady)
|
||||
public:
|
||||
Sound(const QUrl& url, bool isStereo = false);
|
||||
|
||||
bool isStereo() const { return _isStereo; }
|
||||
|
||||
bool isReady() const { return _isReady; }
|
||||
|
||||
const QByteArray& getByteArray() { return _byteArray; }
|
||||
|
||||
private:
|
||||
QByteArray _byteArray;
|
||||
bool _isStereo;
|
||||
bool _isReady;
|
||||
|
||||
void trimFrames();
|
||||
void downSample(const QByteArray& rawAudioByteArray);
|
||||
|
@ -40,4 +42,11 @@ private:
|
|||
virtual void downloadFinished(QNetworkReply* reply);
|
||||
};
|
||||
|
||||
typedef QSharedPointer<Sound> SharedSoundPointer;
|
||||
|
||||
Q_DECLARE_METATYPE(SharedSoundPointer)
|
||||
|
||||
QScriptValue soundToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in);
|
||||
void soundFromScriptValue(const QScriptValue& object, SharedSoundPointer& out);
|
||||
|
||||
#endif // hifi_Sound_h
|
||||
|
|
|
@ -13,8 +13,17 @@
|
|||
|
||||
#include "SoundCache.h"
|
||||
|
||||
static int soundPointerMetaTypeId = qRegisterMetaType<SharedSoundPointer>();
|
||||
|
||||
SoundCache& SoundCache::getInstance() {
|
||||
static SoundCache staticInstance;
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
SoundCache::SoundCache(QObject* parent) :
|
||||
ResourceCache(parent) {
|
||||
ResourceCache(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SharedSoundPointer SoundCache::getSound(const QUrl& url) {
|
||||
|
@ -24,10 +33,11 @@ SharedSoundPointer SoundCache::getSound(const QUrl& url) {
|
|||
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
qDebug() << "Requesting sound at" << url.toString() << "from SoundCache";
|
||||
return getResource(url).staticCast<Sound>();
|
||||
}
|
||||
|
||||
QSharedPointer<Resource> SoundCache::createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||
bool delayLoad, const void* extra) {
|
||||
bool delayLoad, const void* extra) {
|
||||
return QSharedPointer<Resource>(new Sound(url), &Resource::allReferencesCleared);
|
||||
}
|
|
@ -16,22 +16,19 @@
|
|||
|
||||
#include "Sound.h"
|
||||
|
||||
typedef QSharedPointer<Sound> SharedSoundPointer;
|
||||
|
||||
/// Scriptable interface for FBX animation loading.
|
||||
/// Scriptable interface for sound loading.
|
||||
class SoundCache : public ResourceCache {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SoundCache(QObject* parent = NULL);
|
||||
static SoundCache& getInstance();
|
||||
|
||||
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
|
||||
|
||||
protected:
|
||||
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url,
|
||||
const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra);
|
||||
private:
|
||||
SoundCache(QObject* parent = NULL);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(SharedSoundPointer)
|
||||
|
||||
#endif // hifi_SoundCache_h
|
|
@ -168,7 +168,7 @@ void Player::setupAudioThread() {
|
|||
_audioThread = new QThread();
|
||||
_options.position = _avatar->getPosition();
|
||||
_options.orientation = _avatar->getOrientation();
|
||||
_injector.reset(new AudioInjector(_recording->getAudio(), _options), &QObject::deleteLater);
|
||||
_injector.reset(new AudioInjector(_recording->getAudioData(), _options), &QObject::deleteLater);
|
||||
_injector->moveToThread(_audioThread);
|
||||
_audioThread->start();
|
||||
QMetaObject::invokeMethod(_injector.data(), "injectAudio", Qt::QueuedConnection);
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
|
||||
ResourceCache::ResourceCache(QObject* parent) :
|
||||
QObject(parent),
|
||||
_lastLRUKey(0) {
|
||||
_lastLRUKey(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ResourceCache::~ResourceCache() {
|
||||
|
@ -291,7 +293,7 @@ void Resource::makeRequest() {
|
|||
connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
|
||||
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));
|
||||
connect(_reply, SIGNAL(finished()), SLOT(handleReplyFinished()));
|
||||
|
||||
|
||||
_replyTimer = new QTimer(this);
|
||||
connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout()));
|
||||
_replyTimer->setSingleShot(true);
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <NetworkAccessManager.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <Sound.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <VoxelDetail.h>
|
||||
|
@ -47,14 +46,6 @@
|
|||
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
|
||||
EntityScriptingInterface ScriptEngine::_entityScriptingInterface;
|
||||
|
||||
static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* engine) {
|
||||
QUrl soundURL = QUrl(context->argument(0).toString());
|
||||
bool isStereo = context->argument(1).toBool();
|
||||
QScriptValue soundScriptValue = engine->newQObject(new Sound(soundURL, isStereo), QScriptEngine::ScriptOwnership);
|
||||
|
||||
return soundScriptValue;
|
||||
}
|
||||
|
||||
static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){
|
||||
qDebug() << "script:print()<<" << context->argument(0).toString();
|
||||
QString message = context->argument(0).toString()
|
||||
|
@ -263,10 +254,6 @@ void ScriptEngine::init() {
|
|||
QScriptValue printConstructorValue = newFunction(debugPrint);
|
||||
globalObject().setProperty("print", printConstructorValue);
|
||||
|
||||
QScriptValue soundConstructorValue = newFunction(soundConstructor);
|
||||
QScriptValue soundMetaObject = newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||
globalObject().setProperty("Sound", soundMetaObject);
|
||||
|
||||
QScriptValue localVoxelsValue = scriptValueFromQMetaObject<LocalVoxels>();
|
||||
globalObject().setProperty("LocalVoxels", localVoxelsValue);
|
||||
|
||||
|
|
|
@ -119,8 +119,6 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont
|
|||
char dateString[100];
|
||||
strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime);
|
||||
|
||||
prefixString.append(QString(" [%1]").arg(dateString));
|
||||
|
||||
if (_shouldOutputPID) {
|
||||
prefixString.append(QString(" [%1").arg(getpid()));
|
||||
|
||||
|
|
Loading…
Reference in a new issue