QAudioOutput and QSoundEffect now have a category property so that system volume mixing or processing can be applied. Initially just pulseaudio supports this but Windows Vista etc should also work. Change-Id: I6855b08367e5a055ac7dfcffd644c98bfd7c5a4e Reviewed-by: Ling Hu <ling.hu@nokia.com>
417 lines
12 KiB
C++
417 lines
12 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
** Contact: http://www.qt-project.org/
|
|
**
|
|
** This file is part of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** GNU Lesser General Public License Usage
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this
|
|
** file. Please review the following information to ensure the GNU Lesser
|
|
** General Public License version 2.1 requirements will be met:
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU General
|
|
** Public License version 3.0 as published by the Free Software Foundation
|
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
|
** file. Please review the following information to ensure the GNU General
|
|
** Public License version 3.0 requirements will be met:
|
|
** http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
** Other Usage
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include "qaudio.h"
|
|
#include "qaudiodeviceinfo.h"
|
|
#include "qaudiosystem.h"
|
|
#include "qaudiooutput.h"
|
|
|
|
#include "qaudiodevicefactory_p.h"
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
\class QAudioOutput
|
|
\brief The QAudioOutput class provides an interface for sending audio data to an audio output device.
|
|
|
|
\inmodule QtMultimedia
|
|
\ingroup multimedia
|
|
\ingroup multimedia_audio
|
|
|
|
You can construct an audio output with the system's
|
|
\l{QAudioDeviceInfo::defaultOutputDevice()}{default audio output
|
|
device}. It is also possible to create QAudioOutput with a
|
|
specific QAudioDeviceInfo. When you create the audio output, you
|
|
should also send in the QAudioFormat to be used for the playback
|
|
(see the QAudioFormat class description for details).
|
|
|
|
To play a file:
|
|
|
|
Starting to play an audio stream is simply a matter of calling
|
|
start() with a QIODevice. QAudioOutput will then fetch the data it
|
|
needs from the io device. So playing back an audio file is as
|
|
simple as:
|
|
|
|
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio output class members
|
|
|
|
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio output setup
|
|
|
|
The file will start playing assuming that the audio system and
|
|
output device support it. If you run out of luck, check what's
|
|
up with the error() function.
|
|
|
|
After the file has finished playing, we need to stop the device:
|
|
|
|
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio output state changed
|
|
|
|
At any given time, the QAudioOutput will be in one of four states:
|
|
active, suspended, stopped, or idle. These states are described
|
|
by the QAudio::State enum.
|
|
State changes are reported through the stateChanged() signal. You
|
|
can use this signal to, for instance, update the GUI of the
|
|
application; the mundane example here being changing the state of
|
|
a \c { play/pause } button. You request a state change directly
|
|
with suspend(), stop(), reset(), resume(), and start().
|
|
|
|
While the stream is playing, you can set a notify interval in
|
|
milliseconds with setNotifyInterval(). This interval specifies the
|
|
time between two emissions of the notify() signal. This is
|
|
relative to the position in the stream, i.e., if the QAudioOutput
|
|
is in the SuspendedState or the IdleState, the notify() signal is
|
|
not emitted. A typical use-case would be to update a
|
|
\l{QSlider}{slider} that allows seeking in the stream.
|
|
If you want the time since playback started regardless of which
|
|
states the audio output has been in, elapsedUSecs() is the function for you.
|
|
|
|
If an error occurs, you can fetch the \l{QAudio::Error}{error
|
|
type} with the error() function. Please see the QAudio::Error enum
|
|
for a description of the possible errors that are reported. When
|
|
an error is encountered, the state changes to QAudio::StoppedState.
|
|
You can check for errors by connecting to the stateChanged()
|
|
signal:
|
|
|
|
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio output state changed
|
|
|
|
\sa QAudioInput, QAudioDeviceInfo
|
|
*/
|
|
|
|
/*!
|
|
Construct a new audio output and attach it to \a parent.
|
|
The default audio output device is used with the output
|
|
\a format parameters.
|
|
*/
|
|
QAudioOutput::QAudioOutput(const QAudioFormat &format, QObject *parent):
|
|
QObject(parent)
|
|
{
|
|
d = QAudioDeviceFactory::createDefaultOutputDevice(format);
|
|
connect(d, SIGNAL(notify()), SIGNAL(notify()));
|
|
connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
|
|
}
|
|
|
|
/*!
|
|
Construct a new audio output and attach it to \a parent.
|
|
The device referenced by \a audioDevice is used with the output
|
|
\a format parameters.
|
|
*/
|
|
QAudioOutput::QAudioOutput(const QAudioDeviceInfo &audioDevice, const QAudioFormat &format, QObject *parent):
|
|
QObject(parent)
|
|
{
|
|
d = QAudioDeviceFactory::createOutputDevice(audioDevice, format);
|
|
connect(d, SIGNAL(notify()), SIGNAL(notify()));
|
|
connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
|
|
}
|
|
|
|
/*!
|
|
Destroys this audio output.
|
|
|
|
This will release any system resources used and free any buffers.
|
|
*/
|
|
QAudioOutput::~QAudioOutput()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
/*!
|
|
Returns the QAudioFormat being used.
|
|
|
|
*/
|
|
QAudioFormat QAudioOutput::format() const
|
|
{
|
|
return d->format();
|
|
}
|
|
|
|
/*!
|
|
Uses the \a device as the QIODevice to transfer data.
|
|
Passing a QIODevice allows the data to be transferred without any extra code.
|
|
All that is required is to open the QIODevice.
|
|
|
|
If able to successfully output audio data to the systems audio device the
|
|
state() is set to QAudio::ActiveState, error() is set to QAudio::NoError
|
|
and the stateChanged() signal is emitted.
|
|
|
|
If a problem occurs during this process the error() is set to QAudio::OpenError,
|
|
state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
|
|
|
|
\sa QIODevice
|
|
*/
|
|
void QAudioOutput::start(QIODevice* device)
|
|
{
|
|
d->start(device);
|
|
}
|
|
|
|
/*!
|
|
Returns a pointer to the QIODevice being used to handle the data
|
|
transfer. This QIODevice can be used to write() audio data directly.
|
|
|
|
If able to access the systems audio device the state() is set to
|
|
QAudio::IdleState, error() is set to QAudio::NoError
|
|
and the stateChanged() signal is emitted.
|
|
|
|
If a problem occurs during this process the error() is set to QAudio::OpenError,
|
|
state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
|
|
|
|
\sa QIODevice
|
|
*/
|
|
QIODevice* QAudioOutput::start()
|
|
{
|
|
return d->start();
|
|
}
|
|
|
|
/*!
|
|
Stops the audio output, detaching from the system resource.
|
|
|
|
Sets error() to QAudio::NoError, state() to QAudio::StoppedState and
|
|
emit stateChanged() signal.
|
|
*/
|
|
void QAudioOutput::stop()
|
|
{
|
|
d->stop();
|
|
}
|
|
|
|
/*!
|
|
Drops all audio data in the buffers, resets buffers to zero.
|
|
|
|
*/
|
|
void QAudioOutput::reset()
|
|
{
|
|
d->reset();
|
|
}
|
|
|
|
/*!
|
|
Stops processing audio data, preserving buffered audio data.
|
|
|
|
Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
|
|
emits stateChanged() signal.
|
|
*/
|
|
void QAudioOutput::suspend()
|
|
{
|
|
d->suspend();
|
|
}
|
|
|
|
/*!
|
|
Resumes processing audio data after a suspend().
|
|
|
|
Sets error() to QAudio::NoError.
|
|
Sets state() to QAudio::ActiveState if you previously called start(QIODevice*).
|
|
Sets state() to QAudio::IdleState if you previously called start().
|
|
emits stateChanged() signal.
|
|
*/
|
|
void QAudioOutput::resume()
|
|
{
|
|
d->resume();
|
|
}
|
|
|
|
/*!
|
|
Returns the number of free bytes available in the audio buffer.
|
|
|
|
\note The returned value is only valid while in QAudio::ActiveState or QAudio::IdleState
|
|
state, otherwise returns zero.
|
|
*/
|
|
int QAudioOutput::bytesFree() const
|
|
{
|
|
return d->bytesFree();
|
|
}
|
|
|
|
/*!
|
|
Returns the period size in bytes. This is the amount of data required each period
|
|
to prevent buffer underrun, and to ensure uninterrupted playback.
|
|
|
|
\note It is recommended to provide at least enough data for a full period with each
|
|
write operation.
|
|
*/
|
|
int QAudioOutput::periodSize() const
|
|
{
|
|
return d->periodSize();
|
|
}
|
|
|
|
/*!
|
|
Sets the audio buffer size to \a value in bytes.
|
|
|
|
\note This function can be called anytime before start(). Calls to this
|
|
are ignored after start(). It should not be assumed that the buffer size
|
|
set is the actual buffer size used - call bufferSize() anytime after start()
|
|
to return the actual buffer size being used.
|
|
*/
|
|
void QAudioOutput::setBufferSize(int value)
|
|
{
|
|
d->setBufferSize(value);
|
|
}
|
|
|
|
/*!
|
|
Returns the audio buffer size in bytes.
|
|
|
|
If called before start(), returns platform default value.
|
|
If called before start() but setBufferSize() was called prior, returns value set by setBufferSize().
|
|
If called after start(), returns the actual buffer size being used. This may not be what was set previously
|
|
by setBufferSize().
|
|
|
|
*/
|
|
int QAudioOutput::bufferSize() const
|
|
{
|
|
return d->bufferSize();
|
|
}
|
|
|
|
/*!
|
|
Sets the interval for notify() signal to be emitted.
|
|
This is based on the \a ms of audio data processed,
|
|
not on wall clock time.
|
|
The minimum resolution of the timer is platform specific and values
|
|
should be checked with notifyInterval() to confirm the actual value
|
|
being used.
|
|
*/
|
|
void QAudioOutput::setNotifyInterval(int ms)
|
|
{
|
|
d->setNotifyInterval(ms);
|
|
}
|
|
|
|
/*!
|
|
Returns the notify interval in milliseconds.
|
|
*/
|
|
int QAudioOutput::notifyInterval() const
|
|
{
|
|
return d->notifyInterval();
|
|
}
|
|
|
|
/*!
|
|
Returns the amount of audio data processed since start()
|
|
was called (in microseconds).
|
|
*/
|
|
qint64 QAudioOutput::processedUSecs() const
|
|
{
|
|
return d->processedUSecs();
|
|
}
|
|
|
|
/*!
|
|
Returns the microseconds since start() was called, including time in Idle and
|
|
Suspend states.
|
|
*/
|
|
qint64 QAudioOutput::elapsedUSecs() const
|
|
{
|
|
return d->elapsedUSecs();
|
|
}
|
|
|
|
/*!
|
|
Returns the error state.
|
|
*/
|
|
QAudio::Error QAudioOutput::error() const
|
|
{
|
|
return d->error();
|
|
}
|
|
|
|
/*!
|
|
Returns the state of audio processing.
|
|
*/
|
|
QAudio::State QAudioOutput::state() const
|
|
{
|
|
return d->state();
|
|
}
|
|
|
|
/*!
|
|
Sets the volume.
|
|
Where \a volume is between 0.0 and 1.0 inclusive.
|
|
*/
|
|
void QAudioOutput::setVolume(qreal volume)
|
|
{
|
|
d->setVolume(volume);
|
|
}
|
|
|
|
/*!
|
|
Returns the volume between 0.0 and 1.0 inclusive.
|
|
*/
|
|
qreal QAudioOutput::volume() const
|
|
{
|
|
return d->volume();
|
|
}
|
|
|
|
/*!
|
|
Returns the audio category of this audio stream.
|
|
|
|
Some platforms can group audio streams into categories
|
|
and manage their volumes independently, or display them
|
|
in a system mixer control. You can set this property to
|
|
allow the platform to distinguish the purpose of your streams.
|
|
|
|
\sa setCategory()
|
|
*/
|
|
QString QAudioOutput::category() const
|
|
{
|
|
return d->category();
|
|
}
|
|
|
|
/*!
|
|
Sets the audio category of this audio stream.
|
|
|
|
Some platforms can group audio streams into categories
|
|
and manage their volumes independently, or display them
|
|
in a system mixer control. You can set this property to
|
|
allow the platform to distinguish the purpose of your streams.
|
|
|
|
Not all platforms support audio stream categorization. In this
|
|
case, the function call will be ignored.
|
|
|
|
Changing an audio output stream's category while it is opened
|
|
will not take effect until it is reopened.
|
|
\sa category()
|
|
*/
|
|
void QAudioOutput::setCategory(const QString &category)
|
|
{
|
|
d->setCategory(category);
|
|
}
|
|
|
|
/*!
|
|
\fn QAudioOutput::stateChanged(QAudio::State state)
|
|
This signal is emitted when the device \a state has changed.
|
|
This is the current state of the audio output.
|
|
*/
|
|
|
|
/*!
|
|
\fn QAudioOutput::notify()
|
|
This signal is emitted when a certain interval of milliseconds
|
|
of audio data has been processed. The interval is set by
|
|
setNotifyInterval().
|
|
*/
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#include "moc_qaudiooutput.cpp"
|