blob: 43819cfae029a2437bac1bc421ef0cf8e37bd5d5 [file] [log] [blame]
/****************************************************************************
**
** 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;
}
}