| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the plugins of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qaudioengine_openal_p.h" |
| #include "qdebug.h" |
| |
| #define DEBUG_AUDIOENGINE |
| |
| QT_USE_NAMESPACE |
| |
| QSoundSourcePrivate::QSoundSourcePrivate(QObject *parent) |
| : QSoundSource(parent) |
| , m_alSource(0) |
| , m_bindBuffer(0) |
| , m_isReady(false) |
| , m_state(QSoundSource::StoppedState) |
| , m_gain(0) |
| , m_pitch(0) |
| , m_coneInnerAngle(0) |
| , m_coneOuterAngle(0) |
| , m_coneOuterGain(1) |
| { |
| #ifdef DEBUG_AUDIOENGINE |
| qDebug() << "creating new QSoundSourcePrivate"; |
| #endif |
| alGenSources(1, &m_alSource); |
| QAudioEnginePrivate::checkNoError("create source"); |
| setGain(1); |
| setPitch(1); |
| setCone(360, 360, 0); |
| } |
| |
| QSoundSourcePrivate::~QSoundSourcePrivate() |
| { |
| #ifdef DEBUG_AUDIOENGINE |
| qDebug() << "QSoundSourcePrivate::dtor"; |
| #endif |
| release(); |
| } |
| |
| void QSoundSourcePrivate::release() |
| { |
| if (m_alSource) { |
| #ifdef DEBUG_AUDIOENGINE |
| qDebug() << "QSoundSourcePrivate::release"; |
| #endif |
| stop(); |
| unbindBuffer(); |
| alDeleteSources(1, &m_alSource); |
| QAudioEnginePrivate::checkNoError("delete source"); |
| m_alSource = 0; |
| } |
| } |
| |
| void QSoundSourcePrivate::bindBuffer(QSoundBuffer* soundBuffer) |
| { |
| unbindBuffer(); |
| Q_ASSERT(soundBuffer->state() == QSoundBuffer::Ready); |
| m_bindBuffer = qobject_cast<QSoundBufferPrivateAL*>(soundBuffer); |
| m_bindBuffer->bindToSource(m_alSource); |
| m_isReady = true; |
| } |
| |
| void QSoundSourcePrivate::unbindBuffer() |
| { |
| if (m_bindBuffer) { |
| m_bindBuffer->unbindFromSource(m_alSource); |
| m_bindBuffer = 0; |
| } |
| m_isReady = false; |
| if (m_state != QSoundSource::StoppedState) { |
| m_state = QSoundSource::StoppedState; |
| emit stateChanged(m_state); |
| } |
| } |
| |
| void QSoundSourcePrivate::play() |
| { |
| if (!m_alSource || !m_isReady) |
| return; |
| alSourcePlay(m_alSource); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("play"); |
| #endif |
| emit activate(this); |
| } |
| |
| bool QSoundSourcePrivate::isLooping() const |
| { |
| if (!m_alSource) |
| return false; |
| ALint looping = 0; |
| alGetSourcei(m_alSource, AL_LOOPING, &looping); |
| return looping == AL_TRUE ? true : false; |
| } |
| |
| void QSoundSourcePrivate::pause() |
| { |
| if (!m_alSource || !m_isReady) |
| return; |
| alSourcePause(m_alSource); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("pause"); |
| #endif |
| } |
| |
| void QSoundSourcePrivate::stop() |
| { |
| if (!m_alSource) |
| return; |
| alSourceStop(m_alSource); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("stop"); |
| #endif |
| } |
| |
| QSoundSource::State QSoundSourcePrivate::state() const |
| { |
| return m_state; |
| } |
| |
| void QSoundSourcePrivate::checkState() |
| { |
| QSoundSource::State st; |
| st = QSoundSource::StoppedState; |
| if (m_alSource && m_isReady) { |
| ALint s; |
| alGetSourcei(m_alSource, AL_SOURCE_STATE, &s); |
| switch (s) { |
| case AL_PLAYING: |
| st = QSoundSource::PlayingState; |
| break; |
| case AL_PAUSED: |
| st = QSoundSource::PausedState; |
| break; |
| } |
| } |
| if (st == m_state) |
| return; |
| m_state = st; |
| emit stateChanged(m_state); |
| } |
| |
| void QSoundSourcePrivate::setLooping(bool looping) |
| { |
| if (!m_alSource) |
| return; |
| alSourcei(m_alSource, AL_LOOPING, looping ? AL_TRUE : AL_FALSE); |
| } |
| |
| void QSoundSourcePrivate::setPosition(const QVector3D& position) |
| { |
| if (!m_alSource) |
| return; |
| alSource3f(m_alSource, AL_POSITION, position.x(), position.y(), position.z()); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set position"); |
| #endif |
| } |
| |
| void QSoundSourcePrivate::setDirection(const QVector3D& direction) |
| { |
| if (!m_alSource) |
| return; |
| alSource3f(m_alSource, AL_DIRECTION, direction.x(), direction.y(), direction.z()); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set direction"); |
| #endif |
| } |
| |
| void QSoundSourcePrivate::setVelocity(const QVector3D& velocity) |
| { |
| if (!m_alSource) |
| return; |
| alSource3f(m_alSource, AL_VELOCITY, velocity.x(), velocity.y(), velocity.z()); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set velocity"); |
| #endif |
| } |
| |
| QVector3D QSoundSourcePrivate::velocity() const |
| { |
| if (!m_alSource) |
| return QVector3D(0, 0, 0); |
| ALfloat x, y, z; |
| alGetSource3f(m_alSource, AL_VELOCITY, &x, &y, &z); |
| return QVector3D(x, y, z); |
| } |
| |
| QVector3D QSoundSourcePrivate::position() const |
| { |
| if (!m_alSource) |
| return QVector3D(0, 0, 0); |
| ALfloat x, y, z; |
| alGetSource3f(m_alSource, AL_POSITION, &x, &y, &z); |
| return QVector3D(x, y, z); |
| } |
| |
| QVector3D QSoundSourcePrivate::direction() const |
| { |
| if (!m_alSource) |
| return QVector3D(0, 1, 0); |
| ALfloat x, y, z; |
| alGetSource3f(m_alSource, AL_DIRECTION, &x, &y, &z); |
| return QVector3D(x, y, z); |
| } |
| |
| void QSoundSourcePrivate::setGain(qreal gain) |
| { |
| if (!m_alSource || gain == m_gain) |
| return; |
| alSourcef(m_alSource, AL_GAIN, gain); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set gain"); |
| #endif |
| m_gain = gain; |
| } |
| |
| void QSoundSourcePrivate::setPitch(qreal pitch) |
| { |
| if (!m_alSource || m_pitch == pitch) |
| return; |
| alSourcef(m_alSource, AL_PITCH, pitch); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set pitch"); |
| #endif |
| m_pitch = pitch; |
| } |
| |
| void QSoundSourcePrivate::setCone(qreal innerAngle, qreal outerAngle, qreal outerGain) |
| { |
| if (innerAngle > outerAngle) |
| outerAngle = innerAngle; |
| Q_ASSERT(outerAngle <= 360 && innerAngle >= 0); |
| |
| //make sure the setting order will always keep outerAngle >= innerAngle in openAL |
| if (outerAngle >= m_coneInnerAngle) { |
| if (m_coneOuterAngle != outerAngle) { |
| alSourcef(m_alSource, AL_CONE_OUTER_ANGLE, outerAngle); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set cone outerAngle"); |
| #endif |
| m_coneOuterAngle = outerAngle; |
| } |
| if (m_coneInnerAngle != innerAngle) { |
| alSourcef(m_alSource, AL_CONE_INNER_ANGLE, innerAngle); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set cone innerAngle"); |
| #endif |
| m_coneInnerAngle = innerAngle; |
| } |
| } else { |
| if (m_coneInnerAngle != innerAngle) { |
| alSourcef(m_alSource, AL_CONE_INNER_ANGLE, innerAngle); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set cone innerAngle"); |
| #endif |
| m_coneInnerAngle = innerAngle; |
| } |
| if (m_coneOuterAngle != outerAngle) { |
| alSourcef(m_alSource, AL_CONE_OUTER_ANGLE, outerAngle); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set cone outerAngle"); |
| #endif |
| m_coneOuterAngle = outerAngle; |
| } |
| } |
| |
| if (outerGain != m_coneOuterGain) { |
| alSourcef(m_alSource, AL_CONE_OUTER_GAIN, outerGain); |
| #ifdef DEBUG_AUDIOENGINE |
| QAudioEnginePrivate::checkNoError("source set cone outerGain"); |
| #endif |
| m_coneOuterGain = outerGain; |
| } |
| } |