413 lines · 10.9 KB · Text
RawDownload
////  Created by HifiExperiments on 12/30/2023//  Copyright 2023 Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "SoundEntityItem.h" #include <QtCore/QDebug> #include "EntitiesLogging.h"#include "EntityItemProperties.h"#include "EntityTree.h"#include "EntityTreeElement.h" EntityItemPointer SoundEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {    std::shared_ptr<SoundEntityItem> entity(new SoundEntityItem(entityID), [](SoundEntityItem* ptr) { ptr->deleteLater(); });    entity->setProperties(properties);    return entity;} // our non-pure virtual subclass for now...SoundEntityItem::SoundEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {    _type = EntityTypes::Sound;} SoundEntityItem::~SoundEntityItem() {    auto manager = DependencyManager::get<AudioInjectorManager>();    if (manager && _injector) {        manager->stop(_injector);    }} EntityItemProperties SoundEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {    EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class @Sound_ENTITY_COPY_TO@     return properties;} bool SoundEntityItem::setSubClassProperties(const EntityItemProperties& properties) {    bool somethingChanged = false; @Sound_ENTITY_SET_FROM@     return somethingChanged;} EntityPropertyFlags SoundEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {    EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); @Sound_REQUESTED_PROPS@     return requestedProperties;} void SoundEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,                                         EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,                                         EntityPropertyFlags& requestedProperties,                                         EntityPropertyFlags& propertyFlags,                                         EntityPropertyFlags& propertiesDidntFit,                                         int& propertyCount,                                         OctreeElement::AppendState& appendState) const {     bool successPropertyFits = true; @Sound_ENTITY_APPEND@ } int SoundEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,                                                      ReadBitstreamToTreeParams& args,                                                      EntityPropertyFlags& propertyFlags, bool overwriteLocalData,                                                      bool& somethingChanged) {     int bytesRead = 0;    const unsigned char* dataAt = data; @Sound_ENTITY_READ@     return bytesRead;} void SoundEntityItem::debugDump() const {    qCDebug(entities) << "SoundEntityItem id:" << getEntityItemID() << "---------------------------------------------";    qCDebug(entities) << "    name:" << _name;    qCDebug(entities) << "    position:" << debugTreeVector(getWorldPosition());    qCDebug(entities) << "    dimensions:" << debugTreeVector(getScaledDimensions());    qCDebug(entities) << "    editedAgo:" << debugTime(getLastEdited(), usecTimestampNow());    qCDebug(entities) << "    pointer:" << this; @Sound_ENTITY_DEBUG@ } bool SoundEntityItem::shouldCreateSound(const EntityTreePointer& tree) const {    bool clientShouldMakeSound = _localOnly || isMyAvatarEntity() || tree->isServerlessMode();    bool serverShouldMakeSound = !_localOnly;    return (clientShouldMakeSound && tree->getIsClient()) || (serverShouldMakeSound && tree->isEntityServer());} void SoundEntityItem::update(const quint64& now) {    const auto tree = getTree();    if (tree) {        std::lock_guard<std::recursive_mutex> lock(_soundLock);         _updateNeeded = false;         withReadLock([&] {            if (shouldCreateSound(tree)) {                _sound = DependencyManager::get<SoundCache>()->getSound(_soundURL);            }        });         if (_sound) {            if (_sound->isLoaded()) {                updateSound(true);            } else {                connect(_sound.data(), &Resource::finished, this, [&] { updateSound(true); });            }        }    }} void SoundEntityItem::locationChanged(bool tellPhysics, bool tellChildren) {    EntityItem::locationChanged(tellPhysics, tellChildren);    updateSound();} void SoundEntityItem::dimensionsChanged() {    EntityItem::dimensionsChanged();    updateSound();} void SoundEntityItem::setSoundURL(const QString& value) {    bool changed = false;    withWriteLock([&] {        if (value != _soundURL) {            _soundURL = value;            changed = true;        }    });     if (changed) {        const auto tree = getTree();        if (!tree) {            _updateNeeded = true;            return;        }         std::lock_guard<std::recursive_mutex> lock(_soundLock);         withReadLock([&] {            if (shouldCreateSound(tree)) {                _sound = DependencyManager::get<SoundCache>()->getSound(_soundURL);            }        });         if (_sound) {            if (_sound->isLoaded()) {                updateSound(true);            } else {                connect(_sound.data(), &Resource::finished, this, [&] { updateSound(true); });            }        }    }} QString SoundEntityItem::getSoundURL() const {    return resultWithReadLock<QString>([&] {        return _soundURL;    });} void SoundEntityItem::setVolume(float value) {    bool changed = false;    withWriteLock([&] {        if (value != _volume) {            _volume = value;            changed = true;        }    });     if (changed) {        updateSound();    }} float SoundEntityItem::getVolume() const {    return resultWithReadLock<float>([&] {        return _volume;    });} void SoundEntityItem::setTimeOffset(float value) {    bool changed = false;    withWriteLock([&] {        if (value != _timeOffset) {            _timeOffset = value;            changed = true;        }    });     if (changed) {        updateSound(true);    }} float SoundEntityItem::getTimeOffset() const {    return resultWithReadLock<float>([&] {        return _timeOffset;    });} void SoundEntityItem::setPitch(float value) {    bool changed = false;    withWriteLock([&] {        if (value != _pitch) {            _pitch = value;            changed = true;        }    });     if (changed) {        updateSound(true);    }} float SoundEntityItem::getPitch() const {    return resultWithReadLock<float>([&] {        return _pitch;    });} void SoundEntityItem::setPlaying(bool value) {    bool changed = false;    withWriteLock([&] {        if (value != _playing) {            _playing = value;            changed = true;        }    });     if (changed) {        updateSound();    }} bool SoundEntityItem::getPlaying() const {    return resultWithReadLock<float>([&] {        return _playing;    });} void SoundEntityItem::setLoop(bool value) {    bool changed = false;    withWriteLock([&] {        if (value != _loop) {            _loop = value;            changed = true;        }    });     if (changed) {        updateSound(true);    }} bool SoundEntityItem::getLoop() const {    return resultWithReadLock<float>([&] {        return _loop;    });} void SoundEntityItem::setPositional(bool value) {    bool changed = false;    withWriteLock([&] {        if (value != _positional) {            _positional = value;            changed = true;        }    });     if (changed) {        updateSound();    }} bool SoundEntityItem::getPositional() const {    return resultWithReadLock<float>([&] {        return _positional;    });} void SoundEntityItem::setLocalOnly(bool value) {    bool changed = false;    withWriteLock([&] {        if (value != _localOnly) {            _localOnly = value;            changed = true;        }    });     if (changed) {        const auto tree = getTree();        if (!tree) {            _updateNeeded = true;            return;        }         std::lock_guard<std::recursive_mutex> lock(_soundLock);         bool createdSound = false;        withReadLock([&] {            if (shouldCreateSound(tree)) {                _sound = DependencyManager::get<SoundCache>()->getSound(_soundURL);                createdSound = true;            }        });         if (!createdSound) {            _sound = nullptr;             if (_injector) {                DependencyManager::get<AudioInjectorManager>()->stop(_injector);                _injector = nullptr;            }        }         if (_sound) {            if (_sound->isLoaded()) {                updateSound(true);            } else {                connect(_sound.data(), &Resource::finished, this, [&] { updateSound(true); });            }        }    }} bool SoundEntityItem::getLocalOnly() const {    return resultWithReadLock<float>([&] {        return _localOnly;    });} bool SoundEntityItem::restartSound(bool lock) {    if (lock) {        _soundLock.lock();    }     if (!_sound) {        if (lock) {            _soundLock.unlock();        }        return false;    }     AudioInjectorOptions options;    withReadLock([&] {        const glm::quat orientation = getWorldOrientation();        options.position = getWorldPosition() + orientation * (getScaledDimensions() * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));        options.positionSet = _positional;        options.volume = _volume;        options.loop = _loop;        options.orientation = orientation;        options.localOnly = _localOnly || _sound->isAmbisonic(); // force localOnly when ambisonic        options.secondOffset = _timeOffset;        options.pitch = _pitch;    });     // stereo option isn't set from script, this comes from sound metadata or filename    options.stereo = _sound->isStereo();    options.ambisonic = _sound->isAmbisonic();     if (_injector) {        DependencyManager::get<AudioInjectorManager>()->setOptions(_injector, options);    } else {        _injector = DependencyManager::get<AudioInjectorManager>()->playSound(_sound, options);    }     if (lock) {        _soundLock.unlock();    }     return true;} void SoundEntityItem::updateSound(bool restart) {    std::lock_guard<std::recursive_mutex> lock(_soundLock);     if (!_sound) {        return;    }     if (restart) {        if (_injector) {            DependencyManager::get<AudioInjectorManager>()->stop(_injector);            _injector = nullptr;        }    }     if (_playing) {        restartSound();    } else {        if (_injector) {            DependencyManager::get<AudioInjectorManager>()->stop(_injector);            _injector = nullptr;        }    }}