Rename QtMultimediaKit to QtMultimedia.

There are a few legacy bits left in place so it passes CI, and
then qt5.git etc can be updated.

Change-Id: I6b082e50e6958c72fdabc2974992e16d90dafa3a
Reviewed-on: http://codereview.qt-project.org/5368
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jonas Rabbe <jonas.rabbe@nokia.com>
This commit is contained in:
Michael Goddard
2011-10-06 14:31:58 +10:00
committed by Qt by Nokia
parent 55bc4f2b46
commit 03f22bcdaf
395 changed files with 1393 additions and 3088 deletions

View File

@@ -0,0 +1,60 @@
INCLUDEPATH += audio
PUBLIC_HEADERS += audio/qaudio.h \
audio/qaudioformat.h \
audio/qaudioinput.h \
audio/qaudiooutput.h \
audio/qaudiodeviceinfo.h \
audio/qaudiosystemplugin.h \
audio/qaudiosystem.h
PRIVATE_HEADERS += audio/qaudiodevicefactory_p.h audio/qaudiopluginloader_p.h
SOURCES += audio/qaudio.cpp \
audio/qaudioformat.cpp \
audio/qaudiodeviceinfo.cpp \
audio/qaudiooutput.cpp \
audio/qaudioinput.cpp \
audio/qaudiosystemplugin.cpp \
audio/qaudiosystem.cpp \
audio/qaudiodevicefactory.cpp \
audio/qaudiopluginloader.cpp
mac {
PRIVATE_HEADERS += audio/qaudioinput_mac_p.h \
audio/qaudiooutput_mac_p.h \
audio/qaudiodeviceinfo_mac_p.h \
audio/qaudio_mac_p.h
SOURCES += audio/qaudiodeviceinfo_mac_p.cpp \
audio/qaudiooutput_mac_p.cpp \
audio/qaudioinput_mac_p.cpp \
audio/qaudio_mac.cpp
LIBS += -framework ApplicationServices -framework CoreAudio -framework AudioUnit -framework AudioToolbox
}
win32 {
PRIVATE_HEADERS += audio/qaudioinput_win32_p.h audio/qaudiooutput_win32_p.h audio/qaudiodeviceinfo_win32_p.h
SOURCES += audio/qaudiodeviceinfo_win32_p.cpp \
audio/qaudiooutput_win32_p.cpp \
audio/qaudioinput_win32_p.cpp
LIBS += -lwinmm -lstrmiids -lole32 -loleaut32
}
unix:!mac {
contains(config_test_pulseaudio, yes) {
DEFINES += QT_NO_AUDIO_BACKEND
}
else:contains(QT_CONFIG, alsa) {
linux-*|freebsd-*|openbsd-* {
DEFINES += HAS_ALSA
PRIVATE_HEADERS += audio/qaudiooutput_alsa_p.h audio/qaudioinput_alsa_p.h audio/qaudiodeviceinfo_alsa_p.h
SOURCES += audio/qaudiodeviceinfo_alsa_p.cpp \
audio/qaudiooutput_alsa_p.cpp \
audio/qaudioinput_alsa_p.cpp
LIBS_PRIVATE += -lasound
}
}
}

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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>
QT_BEGIN_NAMESPACE
namespace QAudio
{
class RegisterMetaTypes
{
public:
RegisterMetaTypes()
{
qRegisterMetaType<QAudio::Error>();
qRegisterMetaType<QAudio::State>();
qRegisterMetaType<QAudio::Mode>();
}
} _register;
}
/*
\namespace QAudio
\brief The QAudio namespace contains enums used by the audio classes.
\inmodule QtMultimedia
\ingroup multimedia
*/
/*
\enum QAudio::Error
\value NoError No errors have occurred
\value OpenError An error occurred opening the audio device
\value IOError An error occurred during read/write of audio device
\value UnderrunError Audio data is not being fed to the audio device at a fast enough rate
\value FatalError A non-recoverable error has occurred, the audio device is not usable at this time.
*/
/*
\enum QAudio::State
\value ActiveState Audio data is being processed, this state is set after start() is called
and while audio data is available to be processed.
\value SuspendedState The audio device is in a suspended state, this state will only be entered
after suspend() is called.
\value StoppedState The audio device is closed, and is not processing any audio data
\value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state
is set after start() is called and while no audio data is available to be processed.
*/
/*
\enum QAudio::Mode
\value AudioOutput audio output device
\value AudioInput audio input device
*/
QT_END_NAMESPACE

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIO_H
#define QAUDIO_H
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include <QtCore/qmetatype.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
//QTM_SYNC_HEADER_EXPORT QAudio
namespace QAudio
{
enum Error { NoError, OpenError, IOError, UnderrunError, FatalError };
enum State { ActiveState, SuspendedState, StoppedState, IdleState };
enum Mode { AudioInput, AudioOutput };
}
QT_END_NAMESPACE
QT_END_HEADER
Q_DECLARE_METATYPE(QAudio::Error)
Q_DECLARE_METATYPE(QAudio::State)
Q_DECLARE_METATYPE(QAudio::Mode)
#endif // QAUDIO_H

View File

@@ -0,0 +1,145 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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_mac_p.h"
QT_BEGIN_NAMESPACE
// Debugging
QDebug operator<<(QDebug dbg, const QAudioFormat& audioFormat)
{
dbg.nospace() << "QAudioFormat(" <<
audioFormat.frequency() << "," <<
audioFormat.channels() << "," <<
audioFormat.sampleSize()<< "," <<
audioFormat.codec() << "," <<
audioFormat.byteOrder() << "," <<
audioFormat.sampleType() << ")";
return dbg.space();
}
// Conversion
QAudioFormat toQAudioFormat(AudioStreamBasicDescription const& sf)
{
QAudioFormat audioFormat;
audioFormat.setFrequency(sf.mSampleRate);
audioFormat.setChannels(sf.mChannelsPerFrame);
audioFormat.setSampleSize(sf.mBitsPerChannel);
audioFormat.setCodec(QString::fromLatin1("audio/pcm"));
audioFormat.setByteOrder((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian);
QAudioFormat::SampleType type = QAudioFormat::UnSignedInt;
if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
type = QAudioFormat::SignedInt;
else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
type = QAudioFormat::Float;
audioFormat.setSampleType(type);
return audioFormat;
}
AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& audioFormat)
{
AudioStreamBasicDescription sf;
sf.mFormatFlags = kAudioFormatFlagIsPacked;
sf.mSampleRate = audioFormat.frequency();
sf.mFramesPerPacket = 1;
sf.mChannelsPerFrame = audioFormat.channels();
sf.mBitsPerChannel = audioFormat.sampleSize();
sf.mBytesPerFrame = sf.mChannelsPerFrame * (sf.mBitsPerChannel / 8);
sf.mBytesPerPacket = sf.mFramesPerPacket * sf.mBytesPerFrame;
sf.mFormatID = kAudioFormatLinearPCM;
switch (audioFormat.sampleType()) {
case QAudioFormat::SignedInt: sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger; break;
case QAudioFormat::UnSignedInt: /* default */ break;
case QAudioFormat::Float: sf.mFormatFlags |= kAudioFormatFlagIsFloat; break;
case QAudioFormat::Unknown: default: break;
}
if (audioFormat.byteOrder() == QAudioFormat::BigEndian)
sf.mFormatFlags |= kAudioFormatFlagIsBigEndian;
return sf;
}
// QAudioRingBuffer
QAudioRingBuffer::QAudioRingBuffer(int bufferSize):
m_bufferSize(bufferSize)
{
m_buffer = new char[m_bufferSize];
reset();
}
QAudioRingBuffer::~QAudioRingBuffer()
{
delete m_buffer;
}
int QAudioRingBuffer::used() const
{
return m_bufferUsed;
}
int QAudioRingBuffer::free() const
{
return m_bufferSize - m_bufferUsed;
}
int QAudioRingBuffer::size() const
{
return m_bufferSize;
}
void QAudioRingBuffer::reset()
{
m_readPos = 0;
m_writePos = 0;
m_bufferUsed = 0;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,145 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIO_MAC_P_H
#define QAUDIO_MAC_P_H
#include <CoreAudio/CoreAudio.h>
#include <QtCore/qdebug.h>
#include <QtCore/qatomic.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
extern QDebug operator<<(QDebug dbg, const QAudioFormat& audioFormat);
extern QAudioFormat toQAudioFormat(const AudioStreamBasicDescription& streamFormat);
extern AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& audioFormat);
class QAudioRingBuffer
{
public:
typedef QPair<char*, int> Region;
QAudioRingBuffer(int bufferSize);
~QAudioRingBuffer();
Region acquireReadRegion(int size)
{
const int used = m_bufferUsed.fetchAndAddAcquire(0);
if (used > 0) {
const int readSize = qMin(size, qMin(m_bufferSize - m_readPos, used));
return readSize > 0 ? Region(m_buffer + m_readPos, readSize) : Region(0, 0);
}
return Region(0, 0);
}
void releaseReadRegion(Region const& region)
{
m_readPos = (m_readPos + region.second) % m_bufferSize;
m_bufferUsed.fetchAndAddRelease(-region.second);
}
Region acquireWriteRegion(int size)
{
const int free = m_bufferSize - m_bufferUsed.fetchAndAddAcquire(0);
if (free > 0) {
const int writeSize = qMin(size, qMin(m_bufferSize - m_writePos, free));
return writeSize > 0 ? Region(m_buffer + m_writePos, writeSize) : Region(0, 0);
}
return Region(0, 0);
}
void releaseWriteRegion(Region const& region)
{
m_writePos = (m_writePos + region.second) % m_bufferSize;
m_bufferUsed.fetchAndAddRelease(region.second);
}
int used() const;
int free() const;
int size() const;
void reset();
private:
int m_bufferSize;
int m_readPos;
int m_writePos;
char* m_buffer;
QAtomicInt m_bufferUsed;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIO_MAC_P_H

View File

@@ -0,0 +1,288 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <QtCore/qdebug.h>
#include "qaudiosystem.h"
#include "qaudiosystemplugin.h"
#include "qaudiopluginloader_p.h"
#include "qaudiodevicefactory_p.h"
#ifndef QT_NO_AUDIO_BACKEND
#if defined(Q_OS_WIN)
#include "qaudiodeviceinfo_win32_p.h"
#include "qaudiooutput_win32_p.h"
#include "qaudioinput_win32_p.h"
#elif defined(Q_OS_MAC)
#include "qaudiodeviceinfo_mac_p.h"
#include "qaudiooutput_mac_p.h"
#include "qaudioinput_mac_p.h"
#elif defined(HAS_ALSA)
#include "qaudiodeviceinfo_alsa_p.h"
#include "qaudiooutput_alsa_p.h"
#include "qaudioinput_alsa_p.h"
#endif
#endif
QT_BEGIN_NAMESPACE
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
Q_GLOBAL_STATIC_WITH_ARGS(QAudioPluginLoader, audioLoader,
(QAudioSystemFactoryInterface_iid, QLatin1String("/audio"), Qt::CaseInsensitive))
#endif
class QNullDeviceInfo : public QAbstractAudioDeviceInfo
{
public:
QAudioFormat preferredFormat() const { qWarning()<<"using null deviceinfo, none available"; return QAudioFormat(); }
bool isFormatSupported(const QAudioFormat& ) const { return false; }
QAudioFormat nearestFormat(const QAudioFormat& ) const { return QAudioFormat(); }
QString deviceName() const { return QString(); }
QStringList supportedCodecs() { return QStringList(); }
QList<int> supportedSampleRates() { return QList<int>(); }
QList<int> supportedChannelCounts() { return QList<int>(); }
QList<int> supportedSampleSizes() { return QList<int>(); }
QList<QAudioFormat::Endian> supportedByteOrders() { return QList<QAudioFormat::Endian>(); }
QList<QAudioFormat::SampleType> supportedSampleTypes() { return QList<QAudioFormat::SampleType>(); }
};
class QNullInputDevice : public QAbstractAudioInput
{
public:
void start(QIODevice*) { qWarning()<<"using null input device, none available";}
QIODevice* start() { qWarning()<<"using null input device, none available"; return 0; }
void stop() {}
void reset() {}
void suspend() {}
void resume() {}
int bytesReady() const { return 0; }
int periodSize() const { return 0; }
void setBufferSize(int ) {}
int bufferSize() const { return 0; }
void setNotifyInterval(int ) {}
int notifyInterval() const { return 0; }
qint64 processedUSecs() const { return 0; }
qint64 elapsedUSecs() const { return 0; }
QAudio::Error error() const { return QAudio::OpenError; }
QAudio::State state() const { return QAudio::StoppedState; }
void setFormat(const QAudioFormat&) {}
QAudioFormat format() const { return QAudioFormat(); }
};
class QNullOutputDevice : public QAbstractAudioOutput
{
public:
void start(QIODevice*) {qWarning()<<"using null output device, none available";}
QIODevice* start() { qWarning()<<"using null output device, none available"; return 0; }
void stop() {}
void reset() {}
void suspend() {}
void resume() {}
int bytesFree() const { return 0; }
int periodSize() const { return 0; }
void setBufferSize(int ) {}
int bufferSize() const { return 0; }
void setNotifyInterval(int ) {}
int notifyInterval() const { return 0; }
qint64 processedUSecs() const { return 0; }
qint64 elapsedUSecs() const { return 0; }
QAudio::Error error() const { return QAudio::OpenError; }
QAudio::State state() const { return QAudio::StoppedState; }
void setFormat(const QAudioFormat&) {}
QAudioFormat format() const { return QAudioFormat(); }
};
QList<QAudioDeviceInfo> QAudioDeviceFactory::availableDevices(QAudio::Mode mode)
{
QList<QAudioDeviceInfo> devices;
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
foreach (const QByteArray &handle, QAudioDeviceInfoInternal::availableDevices(mode))
devices << QAudioDeviceInfo(QLatin1String("builtin"), handle, mode);
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioPluginLoader* l = audioLoader();
foreach (const QString& key, l->keys()) {
QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(l->instance(key));
if (plugin) {
foreach (QByteArray const& handle, plugin->availableDevices(mode))
devices << QAudioDeviceInfo(key, handle, mode);
}
delete plugin;
}
#endif
return devices;
}
QAudioDeviceInfo QAudioDeviceFactory::defaultInputDevice()
{
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(QLatin1String("default")));
if (plugin) {
QList<QByteArray> list = plugin->availableDevices(QAudio::AudioInput);
if (list.size() > 0)
return QAudioDeviceInfo(QLatin1String("default"), list.at(0), QAudio::AudioInput);
}
#endif
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultInputDevice(), QAudio::AudioInput);
#endif
#endif
return QAudioDeviceInfo();
}
QAudioDeviceInfo QAudioDeviceFactory::defaultOutputDevice()
{
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(QLatin1String("default")));
if (plugin) {
QList<QByteArray> list = plugin->availableDevices(QAudio::AudioOutput);
if (list.size() > 0)
return QAudioDeviceInfo(QLatin1String("default"), list.at(0), QAudio::AudioOutput);
}
#endif
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultOutputDevice(), QAudio::AudioOutput);
#endif
#endif
return QAudioDeviceInfo();
}
QAbstractAudioDeviceInfo* QAudioDeviceFactory::audioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode)
{
QAbstractAudioDeviceInfo *rc = 0;
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
if (realm == QLatin1String("builtin"))
return new QAudioDeviceInfoInternal(handle, mode);
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin =
qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(realm));
if (plugin)
rc = plugin->createDeviceInfo(handle, mode);
#endif
return rc == 0 ? new QNullDeviceInfo() : rc;
}
QAbstractAudioInput* QAudioDeviceFactory::createDefaultInputDevice(QAudioFormat const &format)
{
return createInputDevice(defaultInputDevice(), format);
}
QAbstractAudioOutput* QAudioDeviceFactory::createDefaultOutputDevice(QAudioFormat const &format)
{
return createOutputDevice(defaultOutputDevice(), format);
}
QAbstractAudioInput* QAudioDeviceFactory::createInputDevice(QAudioDeviceInfo const& deviceInfo, QAudioFormat const &format)
{
if (deviceInfo.isNull())
return new QNullInputDevice();
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
if (deviceInfo.realm() == QLatin1String("builtin")) {
QAbstractAudioInput* p = new QAudioInputPrivate(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin =
qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(deviceInfo.realm()));
if (plugin) {
QAbstractAudioInput* p = plugin->createInput(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
return new QNullInputDevice();
}
QAbstractAudioOutput* QAudioDeviceFactory::createOutputDevice(QAudioDeviceInfo const& deviceInfo, QAudioFormat const &format)
{
if (deviceInfo.isNull())
return new QNullOutputDevice();
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
if (deviceInfo.realm() == QLatin1String("builtin")) {
QAbstractAudioOutput* p = new QAudioOutputPrivate(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin =
qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(deviceInfo.realm()));
if (plugin) {
QAbstractAudioOutput* p = plugin->createOutput(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
return new QNullOutputDevice();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,100 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEFACTORY_P_H
#define QAUDIODEVICEFACTORY_P_H
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include "qaudiodeviceinfo.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAbstractAudioInput;
class QAbstractAudioOutput;
class QAbstractAudioDeviceInfo;
class QAudioDeviceFactory
{
public:
static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode);
static QAudioDeviceInfo defaultInputDevice();
static QAudioDeviceInfo defaultOutputDevice();
static QAbstractAudioDeviceInfo* audioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode);
static QAbstractAudioInput* createDefaultInputDevice(QAudioFormat const &format);
static QAbstractAudioOutput* createDefaultOutputDevice(QAudioFormat const &format);
static QAbstractAudioInput* createInputDevice(QAudioDeviceInfo const &device, QAudioFormat const &format);
static QAbstractAudioOutput* createOutputDevice(QAudioDeviceInfo const &device, QAudioFormat const &format);
static QAbstractAudioInput* createNullInput();
static QAbstractAudioOutput* createNullOutput();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIODEVICEFACTORY_P_H

View File

@@ -0,0 +1,483 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudiodevicefactory_p.h"
#include "qaudiosystem.h"
#include "qaudiodeviceinfo.h"
#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
class QAudioDeviceInfoPrivate : public QSharedData
{
public:
QAudioDeviceInfoPrivate():info(0) {}
QAudioDeviceInfoPrivate(const QString &r, const QByteArray &h, QAudio::Mode m):
realm(r), handle(h), mode(m)
{
if (!handle.isEmpty())
info = QAudioDeviceFactory::audioDeviceInfo(realm, handle, mode);
else
info = NULL;
}
QAudioDeviceInfoPrivate(const QAudioDeviceInfoPrivate &other):
QSharedData(other),
realm(other.realm), handle(other.handle), mode(other.mode)
{
info = QAudioDeviceFactory::audioDeviceInfo(realm, handle, mode);
}
QAudioDeviceInfoPrivate& operator=(const QAudioDeviceInfoPrivate &other)
{
delete info;
realm = other.realm;
handle = other.handle;
mode = other.mode;
info = QAudioDeviceFactory::audioDeviceInfo(realm, handle, mode);
return *this;
}
~QAudioDeviceInfoPrivate()
{
delete info;
}
QString realm;
QByteArray handle;
QAudio::Mode mode;
QAbstractAudioDeviceInfo* info;
};
/*!
\class QAudioDeviceInfo
\brief The QAudioDeviceInfo class provides an interface to query audio devices and their functionality.
\inmodule QtMultimedia
\ingroup multimedia
QAudioDeviceInfo lets you query for audio devices--such as sound
cards and USB headsets--that are currently available on the system.
The audio devices available are dependent on the platform or audio plugins installed.
A QAudioDeviceInfo is used by Qt to construct
classes that communicate with the device--such as
QAudioInput, and QAudioOutput.
You can also query each device for the formats it supports. A
format in this context is a set consisting of a specific byte
order, channel, codec, frequency, sample rate, and sample type. A
format is represented by the QAudioFormat class.
The values supported by the the device for each of these
parameters can be fetched with
supportedByteOrders(), supportedChannelCounts(), supportedCodecs(),
supportedSampleRates(), supportedSampleSizes(), and
supportedSampleTypes(). The combinations supported are dependent on the platform,
audio plugins installed and the audio device capabilities. If you need a
specific format, you can check if
the device supports it with isFormatSupported(), or fetch a
supported format that is as close as possible to the format with
nearestFormat(). For instance:
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Setting audio format
The static
functions defaultInputDevice(), defaultOutputDevice(), and
availableDevices() let you get a list of all available
devices. Devices are fetched according to the value of mode
this is specified by the \l {QAudio}::Mode enum.
The QAudioDeviceInfo returned are only valid for the \l {QAudio}::Mode.
For instance:
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Dumping audio formats
In this code sample, we loop through all devices that are able to output
sound, i.e., play an audio stream in a supported format. For each device we
find, we simply print the deviceName().
\sa QAudioOutput, QAudioInput
*/
/*!
Constructs an empty QAudioDeviceInfo object.
*/
QAudioDeviceInfo::QAudioDeviceInfo():
d(new QAudioDeviceInfoPrivate)
{
}
/*!
Constructs a copy of \a other.
\since 1.0
*/
QAudioDeviceInfo::QAudioDeviceInfo(const QAudioDeviceInfo& other):
d(other.d)
{
}
/*!
Destroy this audio device info.
*/
QAudioDeviceInfo::~QAudioDeviceInfo()
{
}
/*!
Sets the QAudioDeviceInfo object to be equal to \a other.
\since 1.0
*/
QAudioDeviceInfo& QAudioDeviceInfo::operator=(const QAudioDeviceInfo &other)
{
d = other.d;
return *this;
}
/*!
Returns whether this QAudioDeviceInfo object holds a device definition.
\since 1.0
*/
bool QAudioDeviceInfo::isNull() const
{
return d->info == 0;
}
/*!
Returns the human readable name of the audio device.
Device names vary depending on the platform/audio plugin being used.
They are a unique string identifier for the audio device.
eg. default, Intel, U0x46d0x9a4
\since 1.0
*/
QString QAudioDeviceInfo::deviceName() const
{
return isNull() ? QString() : d->info->deviceName();
}
/*!
Returns true if the supplied \a settings are supported by the audio
device described by this QAudioDeviceInfo.
\since 1.0
*/
bool QAudioDeviceInfo::isFormatSupported(const QAudioFormat &settings) const
{
return isNull() ? false : d->info->isFormatSupported(settings);
}
/*!
Returns the default audio format settings for this device.
These settings are provided by the platform/audio plugin being used.
They are also dependent on the \l {QAudio}::Mode being used.
A typical audio system would provide something like:
\list
\o Input settings: 8000Hz mono 8 bit.
\o Output settings: 44100Hz stereo 16 bit little endian.
\endlist
\since 1.0
*/
QAudioFormat QAudioDeviceInfo::preferredFormat() const
{
return isNull() ? QAudioFormat() : d->info->preferredFormat();
}
/*!
Returns the closest QAudioFormat to the supplied \a settings that the system supports.
These settings are provided by the platform/audio plugin being used.
They are also dependent on the \l {QAudio}::Mode being used.
\since 1.0
*/
QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const
{
if (isFormatSupported(settings))
return settings;
QAudioFormat nearest = settings;
QList<QString> testCodecs = supportedCodecs();
QList<int> testChannels = supportedChannels();
QList<QAudioFormat::Endian> testByteOrders = supportedByteOrders();
QList<QAudioFormat::SampleType> testSampleTypes;
QList<QAudioFormat::SampleType> sampleTypesAvailable = supportedSampleTypes();
QMap<int,int> testFrequencies;
QList<int> frequenciesAvailable = supportedFrequencies();
QMap<int,int> testSampleSizes;
QList<int> sampleSizesAvailable = supportedSampleSizes();
// Get sorted lists for checking
if (testCodecs.contains(settings.codec())) {
testCodecs.removeAll(settings.codec());
testCodecs.insert(0, settings.codec());
}
testChannels.removeAll(settings.channels());
testChannels.insert(0, settings.channels());
testByteOrders.removeAll(settings.byteOrder());
testByteOrders.insert(0, settings.byteOrder());
if (sampleTypesAvailable.contains(settings.sampleType()))
testSampleTypes.append(settings.sampleType());
if (sampleTypesAvailable.contains(QAudioFormat::SignedInt))
testSampleTypes.append(QAudioFormat::SignedInt);
if (sampleTypesAvailable.contains(QAudioFormat::UnSignedInt))
testSampleTypes.append(QAudioFormat::UnSignedInt);
if (sampleTypesAvailable.contains(QAudioFormat::Float))
testSampleTypes.append(QAudioFormat::Float);
if (sampleSizesAvailable.contains(settings.sampleSize()))
testSampleSizes.insert(0,settings.sampleSize());
sampleSizesAvailable.removeAll(settings.sampleSize());
foreach (int size, sampleSizesAvailable) {
int larger = (size > settings.sampleSize()) ? size : settings.sampleSize();
int smaller = (size > settings.sampleSize()) ? settings.sampleSize() : size;
bool isMultiple = ( 0 == (larger % smaller));
int diff = larger - smaller;
testSampleSizes.insert((isMultiple ? diff : diff+100000), size);
}
if (frequenciesAvailable.contains(settings.frequency()))
testFrequencies.insert(0,settings.frequency());
frequenciesAvailable.removeAll(settings.frequency());
foreach (int frequency, frequenciesAvailable) {
int larger = (frequency > settings.frequency()) ? frequency : settings.frequency();
int smaller = (frequency > settings.frequency()) ? settings.frequency() : frequency;
bool isMultiple = ( 0 == (larger % smaller));
int diff = larger - smaller;
testFrequencies.insert((isMultiple ? diff : diff+100000), frequency);
}
// Try to find nearest
foreach (QString codec, testCodecs) {
nearest.setCodec(codec);
foreach (QAudioFormat::Endian order, testByteOrders) {
nearest.setByteOrder(order);
foreach (QAudioFormat::SampleType sample, testSampleTypes) {
nearest.setSampleType(sample);
QMapIterator<int, int> sz(testSampleSizes);
while (sz.hasNext()) {
sz.next();
nearest.setSampleSize(sz.value());
foreach (int channel, testChannels) {
nearest.setChannels(channel);
QMapIterator<int, int> i(testFrequencies);
while (i.hasNext()) {
i.next();
nearest.setFrequency(i.value());
if (isFormatSupported(nearest))
return nearest;
}
}
}
}
}
}
//Fallback
return preferredFormat();
}
/*!
Returns a list of supported codecs.
All platform and plugin implementations should provide support for:
"audio/pcm" - Linear PCM
For writing plugins to support additional codecs refer to:
http://www.iana.org/assignments/media-types/audio/
\since 1.0
*/
QStringList QAudioDeviceInfo::supportedCodecs() const
{
return isNull() ? QStringList() : d->info->supportedCodecs();
}
/*!
Returns a list of supported sample rates (in Hertz).
\since 1.0
*/
QList<int> QAudioDeviceInfo::supportedSampleRates() const
{
return supportedFrequencies();
}
/*!
\obsolete
Use supportedSampleRates() instead.
\since 1.0
*/
QList<int> QAudioDeviceInfo::supportedFrequencies() const
{
return isNull() ? QList<int>() : d->info->supportedSampleRates();
}
/*!
Returns a list of supported channel counts.
This is typically 1 for mono sound, or 2 for stereo sound.
\since 1.0
*/
QList<int> QAudioDeviceInfo::supportedChannelCounts() const
{
return supportedChannels();
}
/*!
\obsolete
Use supportedChannelCount() instead.
\since 1.0
*/
QList<int> QAudioDeviceInfo::supportedChannels() const
{
return isNull() ? QList<int>() : d->info->supportedChannelCounts();
}
/*!
Returns a list of supported sample sizes (in bits).
Typically this will include 8 and 16 bit sample sizes.
\since 1.0
*/
QList<int> QAudioDeviceInfo::supportedSampleSizes() const
{
return isNull() ? QList<int>() : d->info->supportedSampleSizes();
}
/*!
Returns a list of supported byte orders.
\since 1.0
*/
QList<QAudioFormat::Endian> QAudioDeviceInfo::supportedByteOrders() const
{
return isNull() ? QList<QAudioFormat::Endian>() : d->info->supportedByteOrders();
}
/*!
Returns a list of supported sample types.
\since 1.0
*/
QList<QAudioFormat::SampleType> QAudioDeviceInfo::supportedSampleTypes() const
{
return isNull() ? QList<QAudioFormat::SampleType>() : d->info->supportedSampleTypes();
}
/*!
Returns the information for the default input audio device.
All platform and audio plugin implementations provide a default audio device to use.
\since 1.0
*/
QAudioDeviceInfo QAudioDeviceInfo::defaultInputDevice()
{
return QAudioDeviceFactory::defaultInputDevice();
}
/*!
Returns the information for the default output audio device.
All platform and audio plugin implementations provide a default audio device to use.
\since 1.0
*/
QAudioDeviceInfo QAudioDeviceInfo::defaultOutputDevice()
{
return QAudioDeviceFactory::defaultOutputDevice();
}
/*!
Returns a list of audio devices that support \a mode.
\since 1.0
*/
QList<QAudioDeviceInfo> QAudioDeviceInfo::availableDevices(QAudio::Mode mode)
{
return QAudioDeviceFactory::availableDevices(mode);
}
/*!
\internal
\since 1.0
*/
QAudioDeviceInfo::QAudioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode):
d(new QAudioDeviceInfoPrivate(realm, handle, mode))
{
}
/*!
\internal
\since 1.0
*/
QString QAudioDeviceInfo::realm() const
{
return d->realm;
}
/*!
\internal
\since 1.0
*/
QByteArray QAudioDeviceInfo::handle() const
{
return d->handle;
}
/*!
\internal
\since 1.0
*/
QAudio::Mode QAudioDeviceInfo::mode() const
{
return d->mode;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,116 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIODEVICEINFO_H
#define QAUDIODEVICEINFO_H
#include <QtCore/qobject.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include <qaudio.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAudioDeviceFactory;
class QAudioDeviceInfoPrivate;
class Q_MULTIMEDIA_EXPORT QAudioDeviceInfo
{
friend class QAudioDeviceFactory;
public:
QAudioDeviceInfo();
QAudioDeviceInfo(const QAudioDeviceInfo& other);
~QAudioDeviceInfo();
QAudioDeviceInfo& operator=(const QAudioDeviceInfo& other);
bool isNull() const;
QString deviceName() const;
bool isFormatSupported(const QAudioFormat &format) const;
QAudioFormat preferredFormat() const;
QAudioFormat nearestFormat(const QAudioFormat &format) const;
QStringList supportedCodecs() const;
QList<int> supportedFrequencies() const;
QList<int> supportedSampleRates() const;
QList<int> supportedChannels() const;
QList<int> supportedChannelCounts() const;
QList<int> supportedSampleSizes() const;
QList<QAudioFormat::Endian> supportedByteOrders() const;
QList<QAudioFormat::SampleType> supportedSampleTypes() const;
static QAudioDeviceInfo defaultInputDevice();
static QAudioDeviceInfo defaultOutputDevice();
static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode);
private:
QAudioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode);
QString realm() const;
QByteArray handle() const;
QAudio::Mode mode() const;
QSharedDataPointer<QAudioDeviceInfoPrivate> d;
};
QT_END_NAMESPACE
QT_END_HEADER
Q_DECLARE_METATYPE(QAudioDeviceInfo)
#endif // QAUDIODEVICEINFO_H

View File

@@ -0,0 +1,535 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qaudiodeviceinfo_alsa_p.h"
#include <alsa/version.h>
QT_BEGIN_NAMESPACE
QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray dev, QAudio::Mode mode)
{
handle = 0;
device = QLatin1String(dev);
this->mode = mode;
checkSurround();
}
QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
{
close();
}
bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
return testSettings(format);
}
QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
QAudioFormat nearest;
if(mode == QAudio::AudioOutput) {
nearest.setFrequency(44100);
nearest.setChannels(2);
nearest.setByteOrder(QAudioFormat::LittleEndian);
nearest.setSampleType(QAudioFormat::SignedInt);
nearest.setSampleSize(16);
nearest.setCodec(QLatin1String("audio/pcm"));
} else {
nearest.setFrequency(8000);
nearest.setChannels(1);
nearest.setSampleType(QAudioFormat::UnSignedInt);
nearest.setSampleSize(8);
nearest.setCodec(QLatin1String("audio/pcm"));
if(!testSettings(nearest)) {
nearest.setChannels(2);
nearest.setSampleSize(16);
nearest.setSampleType(QAudioFormat::SignedInt);
}
}
return nearest;
}
QString QAudioDeviceInfoInternal::deviceName() const
{
return device;
}
QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
updateLists();
return codecz;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
updateLists();
return freqz;
}
QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
updateLists();
return channelz;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
updateLists();
return sizez;
}
QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
updateLists();
return byteOrderz;
}
QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
updateLists();
return typez;
}
bool QAudioDeviceInfoInternal::open()
{
int err = 0;
QString dev = device;
QList<QByteArray> devices = availableDevices(mode);
if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
if (devices.size() > 0)
dev = QLatin1String(devices.first().constData());
else
return false;
#else
dev = QLatin1String("hw:0,0");
#endif
} else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = device;
#else
int idx = 0;
char *name;
QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);
while(snd_card_get_name(idx,&name) == 0) {
if(dev.contains(QLatin1String(name)))
break;
idx++;
}
dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
}
if(mode == QAudio::AudioOutput) {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
} else {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
}
if(err < 0) {
handle = 0;
return false;
}
return true;
}
void QAudioDeviceInfoInternal::close()
{
if(handle)
snd_pcm_close(handle);
handle = 0;
}
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
// Set nearest to closest settings that do work.
// See if what is in settings will work (return value).
int err = 0;
snd_pcm_t* handle;
snd_pcm_hw_params_t *params;
QString dev = device;
QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = QLatin1String(devices.first().constData());
#else
dev = QLatin1String("hw:0,0");
#endif
} else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = device;
#else
int idx = 0;
char *name;
QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);
while(snd_card_get_name(idx,&name) == 0) {
if(shortName.compare(QLatin1String(name)) == 0)
break;
idx++;
}
dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
}
if(mode == QAudio::AudioOutput) {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
} else {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
}
if(err < 0) {
handle = 0;
return false;
}
bool testChannel = false;
bool testCodec = false;
bool testFreq = false;
bool testType = false;
bool testSize = false;
int dir = 0;
snd_pcm_nonblock( handle, 0 );
snd_pcm_hw_params_alloca( &params );
snd_pcm_hw_params_any( handle, params );
// set the values!
snd_pcm_hw_params_set_channels(handle,params,format.channels());
snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
err = -1;
switch(format.sampleSize()) {
case 8:
if(format.sampleType() == QAudioFormat::SignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
else if(format.sampleType() == QAudioFormat::UnSignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
break;
case 16:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
}
break;
case 32:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
}
}
// For now, just accept only audio/pcm codec
if(!format.codec().startsWith(QLatin1String("audio/pcm"))) {
err=-1;
} else
testCodec = true;
if(err>=0 && format.channels() != -1) {
err = snd_pcm_hw_params_test_channels(handle,params,format.channels());
if(err>=0)
err = snd_pcm_hw_params_set_channels(handle,params,format.channels());
if(err>=0)
testChannel = true;
}
if(err>=0 && format.frequency() != -1) {
err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0);
if(err>=0)
err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
if(err>=0)
testFreq = true;
}
if((err>=0 && format.sampleSize() != -1) &&
(format.sampleType() != QAudioFormat::Unknown)) {
switch(format.sampleSize()) {
case 8:
if(format.sampleType() == QAudioFormat::SignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
else if(format.sampleType() == QAudioFormat::UnSignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
break;
case 16:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
}
break;
case 32:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
}
}
if(err>=0) {
testSize = true;
testType = true;
}
}
if(err>=0)
err = snd_pcm_hw_params(handle, params);
if(err == 0) {
// settings work
// close()
if(handle)
snd_pcm_close(handle);
return true;
}
if(handle)
snd_pcm_close(handle);
return false;
}
void QAudioDeviceInfoInternal::updateLists()
{
// redo all lists based on current settings
freqz.clear();
channelz.clear();
sizez.clear();
byteOrderz.clear();
typez.clear();
codecz.clear();
if(!handle)
open();
if(!handle)
return;
for(int i=0; i<(int)MAX_SAMPLE_RATES; i++) {
//if(snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0)
freqz.append(SAMPLE_RATES[i]);
}
channelz.append(1);
channelz.append(2);
if (surround40) channelz.append(4);
if (surround51) channelz.append(6);
if (surround71) channelz.append(8);
sizez.append(8);
sizez.append(16);
sizez.append(32);
byteOrderz.append(QAudioFormat::LittleEndian);
byteOrderz.append(QAudioFormat::BigEndian);
typez.append(QAudioFormat::SignedInt);
typez.append(QAudioFormat::UnSignedInt);
typez.append(QAudioFormat::Float);
codecz.append(QLatin1String("audio/pcm"));
close();
}
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
QList<QByteArray> allDevices;
QList<QByteArray> devices;
QByteArray filter;
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
// Create a list of all current audio devices that support mode
void **hints, **n;
char *name, *descr, *io;
if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
qWarning() << "no alsa devices available";
return devices;
}
n = hints;
if(mode == QAudio::AudioInput) {
filter = "Input";
} else {
filter = "Output";
}
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
if (name != 0 && qstrcmp(name, "null") != 0) {
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if ((descr != NULL) && ((io == NULL) || (io == filter))) {
QString deviceName = QLatin1String(name);
QString deviceDescription = QLatin1String(descr);
allDevices.append(deviceName.toLocal8Bit().constData());
if (deviceDescription.contains(QLatin1String("Default Audio Device")))
devices.append(deviceName.toLocal8Bit().constData());
}
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
}
++n;
}
snd_device_name_free_hint(hints);
if(devices.size() > 0) {
devices.append("default");
}
#else
int idx = 0;
char* name;
while(snd_card_get_name(idx,&name) == 0) {
devices.append(name);
idx++;
}
if (idx > 0)
devices.append("default");
#endif
#if !defined(Q_WS_MAEMO_6)
if (devices.size() == 0 && allDevices.size() > 0)
return allDevices;
#endif
return devices;
}
QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
QList<QByteArray> devices = availableDevices(QAudio::AudioInput);
if(devices.size() == 0)
return QByteArray();
return devices.first();
}
QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
QList<QByteArray> devices = availableDevices(QAudio::AudioOutput);
if(devices.size() == 0)
return QByteArray();
return devices.first();
}
void QAudioDeviceInfoInternal::checkSurround()
{
QList<QByteArray> devices;
surround40 = false;
surround51 = false;
surround71 = false;
void **hints, **n;
char *name, *descr, *io;
if(snd_device_name_hint(-1, "pcm", &hints) < 0)
return;
n = hints;
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if((name != NULL) && (descr != NULL)) {
QString deviceName = QLatin1String(name);
if (mode == QAudio::AudioOutput) {
if(deviceName.contains(QLatin1String("surround40")))
surround40 = true;
if(deviceName.contains(QLatin1String("surround51")))
surround51 = true;
if(deviceName.contains(QLatin1String("surround71")))
surround71 = true;
}
}
if(name != NULL)
free(name);
if(descr != NULL)
free(descr);
if(io != NULL)
free(io);
++n;
}
snd_device_name_free_hint(hints);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,129 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEINFOALSA_H
#define QAUDIODEVICEINFOALSA_H
#include <alsa/asoundlib.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <QtCore/qdebug.h>
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
const unsigned int MAX_SAMPLE_RATES = 5;
const unsigned int SAMPLE_RATES[] =
{ 8000, 11025, 22050, 44100, 48000 };
class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo
{
Q_OBJECT
public:
QAudioDeviceInfoInternal(QByteArray dev,QAudio::Mode mode);
~QAudioDeviceInfoInternal();
bool testSettings(const QAudioFormat& format) const;
void updateLists();
QAudioFormat preferredFormat() const;
bool isFormatSupported(const QAudioFormat& format) const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode);
private:
bool open();
void close();
void checkSurround();
bool surround40;
bool surround51;
bool surround71;
QString device;
QAudio::Mode mode;
QAudioFormat nearest;
QList<int> freqz;
QList<int> channelz;
QList<int> sizez;
QList<QAudioFormat::Endian> byteOrderz;
QStringList codecz;
QList<QAudioFormat::SampleType> typez;
snd_pcm_t* handle;
snd_pcm_hw_params_t *params;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,351 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qdebug.h>
#include <qaudiodeviceinfo.h>
#include "qaudio_mac_p.h"
#include "qaudiodeviceinfo_mac_p.h"
QT_BEGIN_NAMESPACE
// XXX: remove at some future date
static inline QString cfStringToQString(CFStringRef str)
{
CFIndex length = CFStringGetLength(str);
const UniChar *chars = CFStringGetCharactersPtr(str);
if (chars)
return QString(reinterpret_cast<const QChar *>(chars), length);
UniChar buffer[length];
CFStringGetCharacters(str, CFRangeMake(0, length), buffer);
return QString(reinterpret_cast<const QChar *>(buffer), length);
}
QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray const& handle, QAudio::Mode)
{
QDataStream ds(handle);
quint32 did, tm;
ds >> did >> tm >> name;
deviceId = AudioDeviceID(did);
mode = QAudio::Mode(tm);
}
bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
QAudioDeviceInfoInternal *self = const_cast<QAudioDeviceInfoInternal*>(this);
return format.isValid()
&& format.codec() == QString::fromLatin1("audio/pcm")
&& self->supportedSampleRates().contains(format.sampleRate())
&& self->supportedChannelCounts().contains(format.channelCount())
&& self->supportedSampleSizes().contains(format.sampleSize());
}
QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
QAudioFormat rc;
UInt32 propSize = 0;
if (AudioDeviceGetPropertyInfo(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreams,
&propSize,
0) == noErr) {
const int sc = propSize / sizeof(AudioStreamID);
if (sc > 0) {
AudioStreamID* streams = new AudioStreamID[sc];
if (AudioDeviceGetProperty(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreams,
&propSize,
streams) == noErr) {
for (int i = 0; i < sc; ++i) {
if (AudioStreamGetPropertyInfo(streams[i],
0,
kAudioStreamPropertyPhysicalFormat,
&propSize,
0) == noErr) {
AudioStreamBasicDescription sf;
if (AudioStreamGetProperty(streams[i],
0,
kAudioStreamPropertyPhysicalFormat,
&propSize,
&sf) == noErr) {
rc = toQAudioFormat(sf);
break;
}
}
}
}
delete streams;
}
}
return rc;
}
QString QAudioDeviceInfoInternal::deviceName() const
{
return name;
}
QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
return QStringList() << QString::fromLatin1("audio/pcm");
}
QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
QSet<int> rc;
// Add some common frequencies
rc << 8000 << 11025 << 22050 << 44100;
//
UInt32 propSize = 0;
if (AudioDeviceGetPropertyInfo(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyAvailableNominalSampleRates,
&propSize,
0) == noErr) {
const int pc = propSize / sizeof(AudioValueRange);
if (pc > 0) {
AudioValueRange* vr = new AudioValueRange[pc];
if (AudioDeviceGetProperty(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyAvailableNominalSampleRates,
&propSize,
vr) == noErr) {
for (int i = 0; i < pc; ++i)
rc << vr[i].mMaximum;
}
delete vr;
}
}
return rc.toList();
}
QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
QList<int> rc;
// Can mix down to 1 channel
rc << 1;
UInt32 propSize = 0;
int channels = 0;
if (AudioDeviceGetPropertyInfo(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreamConfiguration,
&propSize,
0) == noErr) {
AudioBufferList* audioBufferList = static_cast<AudioBufferList*>(qMalloc(propSize));
if (audioBufferList != 0) {
if (AudioDeviceGetProperty(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreamConfiguration,
&propSize,
audioBufferList) == noErr) {
for (int i = 0; i < int(audioBufferList->mNumberBuffers); ++i) {
channels += audioBufferList->mBuffers[i].mNumberChannels;
rc << channels;
}
}
qFree(audioBufferList);
}
}
return rc;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
return QList<int>() << 8 << 16 << 24 << 32 << 64;
}
QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian;
}
QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
}
static QByteArray get_device_info(AudioDeviceID audioDevice, QAudio::Mode mode)
{
UInt32 size;
QByteArray device;
QDataStream ds(&device, QIODevice::WriteOnly);
AudioStreamBasicDescription sf;
CFStringRef name;
Boolean isInput = mode == QAudio::AudioInput;
// Id
ds << quint32(audioDevice);
// Mode
size = sizeof(AudioStreamBasicDescription);
if (AudioDeviceGetProperty(audioDevice, 0, isInput, kAudioDevicePropertyStreamFormat,
&size, &sf) != noErr) {
return QByteArray();
}
ds << quint32(mode);
// Name
size = sizeof(CFStringRef);
if (AudioDeviceGetProperty(audioDevice, 0, isInput, kAudioObjectPropertyName,
&size, &name) != noErr) {
qWarning() << "QAudioDeviceInfo: Unable to find device name";
return QByteArray();
}
ds << cfStringToQString(name);
CFRelease(name);
return device;
}
QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
AudioDeviceID audioDevice;
UInt32 size = sizeof(audioDevice);
if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &size,
&audioDevice) != noErr) {
qWarning() << "QAudioDeviceInfo: Unable to find default input device";
return QByteArray();
}
return get_device_info(audioDevice, QAudio::AudioInput);
}
QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
AudioDeviceID audioDevice;
UInt32 size = sizeof(audioDevice);
if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size,
&audioDevice) != noErr) {
qWarning() << "QAudioDeviceInfo: Unable to find default output device";
return QByteArray();
}
return get_device_info(audioDevice, QAudio::AudioOutput);
}
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
QList<QByteArray> devices;
UInt32 propSize = 0;
if (AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &propSize, 0) == noErr) {
const int dc = propSize / sizeof(AudioDeviceID);
if (dc > 0) {
AudioDeviceID* audioDevices = new AudioDeviceID[dc];
if (AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &propSize, audioDevices) == noErr) {
for (int i = 0; i < dc; ++i) {
QByteArray info = get_device_info(audioDevices[i], mode);
if (!info.isNull())
devices << info;
}
}
delete audioDevices;
}
}
return devices;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QDEVICEINFO_MAC_P_H
#define QDEVICEINFO_MAC_P_H
#include <CoreAudio/CoreAudio.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo
{
public:
AudioDeviceID deviceId;
QString name;
QAudio::Mode mode;
QAudioDeviceInfoInternal(QByteArray const& handle, QAudio::Mode mode);
bool isFormatSupported(const QAudioFormat& format) const;
QAudioFormat preferredFormat() const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode mode);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QDEVICEINFO_MAC_P_H

View File

@@ -0,0 +1,465 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <windows.h>
#include <mmsystem.h>
#include "qaudiodeviceinfo_win32_p.h"
#include <dshow.h>
#if defined(Q_CC_MINGW)
extern GUID CLSID_AudioInputDeviceCategory;
#ifndef __IErrorLog_INTERFACE_DEFINED__
#define __IErrorLog_INTERFACE_DEFINED__
DECLARE_INTERFACE_(IErrorLog, IUnknown)
{
STDMETHOD(AddError)(THIS_ LPCOLESTR, EXCEPINFO *) PURE;
};
#endif /* __IErrorLog_INTERFACE_DEFINED__ */
#ifndef __IPropertyBag_INTERFACE_DEFINED__
#define __IPropertyBag_INTERFACE_DEFINED__
const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};
DECLARE_INTERFACE_(IPropertyBag, IUnknown)
{
STDMETHOD(Read)(THIS_ LPCOLESTR, VARIANT *, IErrorLog *) PURE;
STDMETHOD(Write)(THIS_ LPCOLESTR, VARIANT *) PURE;
};
#endif /* __IPropertyBag_INTERFACE_DEFINED__ */
#endif//Q_CC_MINGW
QT_BEGIN_NAMESPACE
// For mingw toolchain mmsystem.h only defines half the defines, so add if needed.
#ifndef WAVE_FORMAT_44M08
#define WAVE_FORMAT_44M08 0x00000100
#define WAVE_FORMAT_44S08 0x00000200
#define WAVE_FORMAT_44M16 0x00000400
#define WAVE_FORMAT_44S16 0x00000800
#define WAVE_FORMAT_48M08 0x00001000
#define WAVE_FORMAT_48S08 0x00002000
#define WAVE_FORMAT_48M16 0x00004000
#define WAVE_FORMAT_48S16 0x00008000
#define WAVE_FORMAT_96M08 0x00010000
#define WAVE_FORMAT_96S08 0x00020000
#define WAVE_FORMAT_96M16 0x00040000
#define WAVE_FORMAT_96S16 0x00080000
#endif
QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray dev, QAudio::Mode mode)
{
QDataStream ds(&dev, QIODevice::ReadOnly);
ds >> devId >> device;
this->mode = mode;
updateLists();
}
QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
{
close();
}
bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
return testSettings(format);
}
QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
QAudioFormat nearest;
if(mode == QAudio::AudioOutput) {
nearest.setFrequency(44100);
nearest.setChannelCount(2);
nearest.setByteOrder(QAudioFormat::LittleEndian);
nearest.setSampleType(QAudioFormat::SignedInt);
nearest.setSampleSize(16);
nearest.setCodec(QLatin1String("audio/pcm"));
} else {
nearest.setFrequency(11025);
nearest.setChannelCount(1);
nearest.setByteOrder(QAudioFormat::LittleEndian);
nearest.setSampleType(QAudioFormat::SignedInt);
nearest.setSampleSize(8);
nearest.setCodec(QLatin1String("audio/pcm"));
}
return nearest;
}
QString QAudioDeviceInfoInternal::deviceName() const
{
return device;
}
QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
updateLists();
return codecz;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
updateLists();
return freqz;
}
QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
updateLists();
return channelz;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
updateLists();
return sizez;
}
QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
updateLists();
return byteOrderz;
}
QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
updateLists();
return typez;
}
bool QAudioDeviceInfoInternal::open()
{
return true;
}
void QAudioDeviceInfoInternal::close()
{
}
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
// Set nearest to closest settings that do work.
// See if what is in settings will work (return value).
bool failed = false;
bool match = false;
// check codec
for( int i = 0; i < codecz.count(); i++) {
if (format.codec() == codecz.at(i))
match = true;
}
if (!match) failed = true;
// check channel
match = false;
if (!failed) {
for( int i = 0; i < channelz.count(); i++) {
if (format.channels() == channelz.at(i)) {
match = true;
break;
}
}
if (!match)
failed = true;
}
// check frequency
match = false;
if (!failed) {
for( int i = 0; i < freqz.count(); i++) {
if (format.frequency() == freqz.at(i)) {
match = true;
break;
}
}
if (!match)
failed = true;
}
// check sample size
match = false;
if (!failed) {
for( int i = 0; i < sizez.count(); i++) {
if (format.sampleSize() == sizez.at(i)) {
match = true;
break;
}
}
if (!match)
failed = true;
}
// check byte order
match = false;
if (!failed) {
for( int i = 0; i < byteOrderz.count(); i++) {
if (format.byteOrder() == byteOrderz.at(i)) {
match = true;
break;
}
}
if (!match)
failed = true;
}
// check sample type
match = false;
if (!failed) {
for( int i = 0; i < typez.count(); i++) {
if (format.sampleType() == typez.at(i)) {
match = true;
break;
}
}
if (!match)
failed = true;
}
if(!failed) {
// settings work
return true;
}
return false;
}
void QAudioDeviceInfoInternal::updateLists()
{
// redo all lists based on current settings
bool match = false;
DWORD fmt = NULL;
if(mode == QAudio::AudioOutput) {
WAVEOUTCAPS woc;
if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
match = true;
fmt = woc.dwFormats;
}
} else {
WAVEINCAPS woc;
if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) {
match = true;
fmt = woc.dwFormats;
}
}
sizez.clear();
freqz.clear();
channelz.clear();
byteOrderz.clear();
typez.clear();
codecz.clear();
if(match) {
if((fmt && WAVE_FORMAT_1M08)
|| (fmt && WAVE_FORMAT_1S08)
|| (fmt && WAVE_FORMAT_2M08)
|| (fmt && WAVE_FORMAT_2S08)
|| (fmt && WAVE_FORMAT_4M08)
|| (fmt && WAVE_FORMAT_4S08)
|| (fmt && WAVE_FORMAT_48M08)
|| (fmt && WAVE_FORMAT_48S08)
|| (fmt && WAVE_FORMAT_96M08)
|| (fmt && WAVE_FORMAT_96S08)
) {
sizez.append(8);
}
if((fmt && WAVE_FORMAT_1M16)
|| (fmt && WAVE_FORMAT_1S16)
|| (fmt && WAVE_FORMAT_2M16)
|| (fmt && WAVE_FORMAT_2S16)
|| (fmt && WAVE_FORMAT_4M16)
|| (fmt && WAVE_FORMAT_4S16)
|| (fmt && WAVE_FORMAT_48M16)
|| (fmt && WAVE_FORMAT_48S16)
|| (fmt && WAVE_FORMAT_96M16)
|| (fmt && WAVE_FORMAT_96S16)
) {
sizez.append(16);
}
if((fmt && WAVE_FORMAT_1M08)
|| (fmt && WAVE_FORMAT_1S08)
|| (fmt && WAVE_FORMAT_1M16)
|| (fmt && WAVE_FORMAT_1S16)) {
freqz.append(11025);
}
if((fmt && WAVE_FORMAT_2M08)
|| (fmt && WAVE_FORMAT_2S08)
|| (fmt && WAVE_FORMAT_2M16)
|| (fmt && WAVE_FORMAT_2S16)) {
freqz.append(22050);
}
if((fmt && WAVE_FORMAT_4M08)
|| (fmt && WAVE_FORMAT_4S08)
|| (fmt && WAVE_FORMAT_4M16)
|| (fmt && WAVE_FORMAT_4S16)) {
freqz.append(44100);
}
if((fmt && WAVE_FORMAT_48M08)
|| (fmt && WAVE_FORMAT_48S08)
|| (fmt && WAVE_FORMAT_48M16)
|| (fmt && WAVE_FORMAT_48S16)) {
freqz.append(48000);
}
if((fmt && WAVE_FORMAT_96M08)
|| (fmt && WAVE_FORMAT_96S08)
|| (fmt && WAVE_FORMAT_96M16)
|| (fmt && WAVE_FORMAT_96S16)) {
freqz.append(96000);
}
channelz.append(1);
channelz.append(2);
if (mode == QAudio::AudioOutput) {
channelz.append(4);
channelz.append(6);
channelz.append(8);
}
byteOrderz.append(QAudioFormat::LittleEndian);
typez.append(QAudioFormat::SignedInt);
typez.append(QAudioFormat::UnSignedInt);
codecz.append(QLatin1String("audio/pcm"));
}
if (freqz.count() > 0)
freqz.prepend(8000);
}
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
Q_UNUSED(mode)
QList<QByteArray> devices;
//enumerate device fullnames through directshow api
CoInitialize(NULL);
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
// Create the System device enumerator
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
reinterpret_cast<void **>(&pDevEnum));
unsigned long iNumDevs = mode == QAudio::AudioOutput ? waveOutGetNumDevs() : waveInGetNumDevs();
if (SUCCEEDED(hr)) {
// Create the enumerator for the audio input/output category
if (pDevEnum->CreateClassEnumerator(
mode == QAudio::AudioOutput ? CLSID_AudioRendererCategory : CLSID_AudioInputDeviceCategory,
&pEnum, 0) == S_OK) {
pEnum->Reset();
// go through and find all audio devices
IMoniker *pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
reinterpret_cast<void **>(&pPropBag));
if (FAILED(hr)) {
pMoniker->Release();
continue; // skip this one
}
// Find if it is a wave device
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(mode == QAudio::AudioOutput ? L"WaveOutID" : L"WaveInID", &var, 0);
if (SUCCEEDED(hr)) {
LONG waveID = var.lVal;
if (waveID >= 0 && waveID < LONG(iNumDevs)) {
VariantClear(&var);
// Find the description
hr = pPropBag->Read(L"FriendlyName", &var, 0);
if (SUCCEEDED(hr)) {
QByteArray device;
QDataStream ds(&device, QIODevice::WriteOnly);
ds << quint32(waveID) << QString::fromWCharArray(var.bstrVal);
devices.append(device);
}
}
}
pPropBag->Release();
pMoniker->Release();
}
}
}
CoUninitialize();
return devices;
}
QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
QList<QByteArray> list = availableDevices(QAudio::AudioOutput);
if (list.size() > 0)
return list.at(0);
else
return QByteArray();
}
QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
QList<QByteArray> list = availableDevices(QAudio::AudioInput);
if (list.size() > 0)
return list.at(0);
else
return QByteArray();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,120 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEINFOWIN_H
#define QAUDIODEVICEINFOWIN_H
#include <QtCore/qbytearray.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <QtCore/qdebug.h>
#include <qaudiodeviceinfo.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
const unsigned int MAX_SAMPLE_RATES = 5;
const unsigned int SAMPLE_RATES[] = { 8000, 11025, 22050, 44100, 48000 };
class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo
{
Q_OBJECT
public:
QAudioDeviceInfoInternal(QByteArray dev,QAudio::Mode mode);
~QAudioDeviceInfoInternal();
bool open();
void close();
bool testSettings(const QAudioFormat& format) const;
void updateLists();
QAudioFormat preferredFormat() const;
bool isFormatSupported(const QAudioFormat& format) const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode);
private:
QAudio::Mode mode;
QString device;
quint32 devId;
QAudioFormat nearest;
QList<int> freqz;
QList<int> channelz;
QList<int> sizez;
QList<QAudioFormat::Endian> byteOrderz;
QStringList codecz;
QList<QAudioFormat::SampleType> typez;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,407 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <QDebug>
#include <qaudioformat.h>
QT_BEGIN_NAMESPACE
class QAudioFormatPrivate : public QSharedData
{
public:
QAudioFormatPrivate()
{
frequency = -1;
channels = -1;
sampleSize = -1;
byteOrder = QAudioFormat::Endian(QSysInfo::ByteOrder);
sampleType = QAudioFormat::Unknown;
}
QAudioFormatPrivate(const QAudioFormatPrivate &other):
QSharedData(other),
codec(other.codec),
byteOrder(other.byteOrder),
sampleType(other.sampleType),
frequency(other.frequency),
channels(other.channels),
sampleSize(other.sampleSize)
{
}
QAudioFormatPrivate& operator=(const QAudioFormatPrivate &other)
{
codec = other.codec;
byteOrder = other.byteOrder;
sampleType = other.sampleType;
frequency = other.frequency;
channels = other.channels;
sampleSize = other.sampleSize;
return *this;
}
QString codec;
QAudioFormat::Endian byteOrder;
QAudioFormat::SampleType sampleType;
int frequency;
int channels;
int sampleSize;
};
/*!
\class QAudioFormat
\brief The QAudioFormat class stores audio stream parameter information.
\inmodule QtMultimedia
\ingroup multimedia
\since 1.0
An audio format specifies how data in an audio stream is arranged,
i.e, how the stream is to be interpreted. The encoding itself is
specified by the codec() used for the stream.
In addition to the encoding, QAudioFormat contains other
parameters that further specify how the audio sample data is arranged.
These are the frequency, the number of channels, the sample size,
the sample type, and the byte order. The following table describes
these in more detail.
\table
\header
\o Parameter
\o Description
\row
\o Sample Rate
\o Samples per second of audio data in Hertz.
\row
\o Number of channels
\o The number of audio channels (typically one for mono
or two for stereo)
\row
\o Sample size
\o How much data is stored in each sample (typically 8
or 16 bits)
\row
\o Sample type
\o Numerical representation of sample (typically signed integer,
unsigned integer or float)
\row
\o Byte order
\o Byte ordering of sample (typically little endian, big endian)
\endtable
This class is typically used in conjunction with QAudioInput or
QAudioOutput to allow you to specify the parameters of the audio
stream being read or written.
You can obtain audio formats compatible with the audio device used
through functions in QAudioDeviceInfo. This class also lets you
query available parameter values for a device, so that you can set
the parameters yourself. See the \l QAudioDeviceInfo class
description for details. You need to know the format of the audio
streams you wish to play or record.
*/
/*!
Construct a new audio format.
Values are initialized as follows:
\list
\o sampleRate() = -1
\o channelCount() = -1
\o sampleSize() = -1
\o byteOrder() = QAudioFormat::Endian(QSysInfo::ByteOrder)
\o sampleType() = QAudioFormat::Unknown
\c codec() = ""
\endlist
*/
QAudioFormat::QAudioFormat():
d(new QAudioFormatPrivate)
{
}
/*!
Construct a new audio format using \a other.
\since 1.0
*/
QAudioFormat::QAudioFormat(const QAudioFormat &other):
d(other.d)
{
}
/*!
Destroy this audio format.
*/
QAudioFormat::~QAudioFormat()
{
}
/*!
Assigns \a other to this QAudioFormat implementation.
\since 1.0
*/
QAudioFormat& QAudioFormat::operator=(const QAudioFormat &other)
{
d = other.d;
return *this;
}
/*!
Returns true if this QAudioFormat is equal to the \a other
QAudioFormat; otherwise returns false.
All elements of QAudioFormat are used for the comparison.
\since 1.0
*/
bool QAudioFormat::operator==(const QAudioFormat &other) const
{
return d->frequency == other.d->frequency &&
d->channels == other.d->channels &&
d->sampleSize == other.d->sampleSize &&
d->byteOrder == other.d->byteOrder &&
d->codec == other.d->codec &&
d->sampleType == other.d->sampleType;
}
/*!
Returns true if this QAudioFormat is not equal to the \a other
QAudioFormat; otherwise returns false.
All elements of QAudioFormat are used for the comparison.
\since 1.0
*/
bool QAudioFormat::operator!=(const QAudioFormat& other) const
{
return !(*this == other);
}
/*!
Returns true if all of the parameters are valid.
\since 1.0
*/
bool QAudioFormat::isValid() const
{
return d->frequency != -1 && d->channels != -1 && d->sampleSize != -1 &&
d->sampleType != QAudioFormat::Unknown && !d->codec.isEmpty();
}
/*!
Sets the sample rate to \a samplerate Hertz.
\since 1.0
*/
void QAudioFormat::setSampleRate(int samplerate)
{
d->frequency = samplerate;
}
/*!
\obsolete
Use setSampleRate() instead.
*/
void QAudioFormat::setFrequency(int frequency)
{
d->frequency = frequency;
}
/*!
Returns the current sample rate in Hertz.
\since 1.0
*/
int QAudioFormat::sampleRate() const
{
return d->frequency;
}
/*!
\obsolete
Use sampleRate() instead.
*/
int QAudioFormat::frequency() const
{
return d->frequency;
}
/*!
Sets the channel count to \a channels.
\since 1.0
*/
void QAudioFormat::setChannelCount(int channels)
{
d->channels = channels;
}
/*!
\obsolete
Use setChannelCount() instead.
*/
void QAudioFormat::setChannels(int channels)
{
d->channels = channels;
}
/*!
Returns the current channel count value.
\since 1.0
*/
int QAudioFormat::channelCount() const
{
return d->channels;
}
/*!
\obsolete
Use channelCount() instead.
*/
int QAudioFormat::channels() const
{
return d->channels;
}
/*!
Sets the sample size to the \a sampleSize specified, in bits.
This is typically 8 or 16, but some systems may support higher sample sizes.
\since 1.0
*/
void QAudioFormat::setSampleSize(int sampleSize)
{
d->sampleSize = sampleSize;
}
/*!
Returns the current sample size value, in bits.
\since 1.0
*/
int QAudioFormat::sampleSize() const
{
return d->sampleSize;
}
/*!
Sets the codec to \a codec.
The parameter to this function should be one of the types
reported by the QAudioDeviceInfo::supportedCodecs() function
for the audio device you are working with.
\since 1.0
\sa QAudioDeviceInfo::supportedCodecs()
*/
void QAudioFormat::setCodec(const QString &codec)
{
d->codec = codec;
}
/*!
Returns the current codec identifier.
\since 1.0
\sa QAudioDeviceInfo::supportedCodecs()
*/
QString QAudioFormat::codec() const
{
return d->codec;
}
/*!
Sets the byteOrder to \a byteOrder.
\since 1.0
*/
void QAudioFormat::setByteOrder(QAudioFormat::Endian byteOrder)
{
d->byteOrder = byteOrder;
}
/*!
Returns the current byteOrder value.
\since 1.0
*/
QAudioFormat::Endian QAudioFormat::byteOrder() const
{
return d->byteOrder;
}
/*!
Sets the sampleType to \a sampleType.
\since 1.0
*/
void QAudioFormat::setSampleType(QAudioFormat::SampleType sampleType)
{
d->sampleType = sampleType;
}
/*!
Returns the current SampleType value.
\since 1.0
*/
QAudioFormat::SampleType QAudioFormat::sampleType() const
{
return d->sampleType;
}
/*!
\enum QAudioFormat::SampleType
\value Unknown Not Set
\value SignedInt Samples are signed integers
\value UnSignedInt Samples are unsigned intergers
\value Float Samples are floats
*/
/*!
\enum QAudioFormat::Endian
\value BigEndian Samples are big endian byte order
\value LittleEndian Samples are little endian byte order
*/
QT_END_NAMESPACE

View File

@@ -0,0 +1,109 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOFORMAT_H
#define QAUDIOFORMAT_H
#include <QtCore/qobject.h>
#include <QtCore/qshareddata.h>
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAudioFormatPrivate;
class Q_MULTIMEDIA_EXPORT QAudioFormat
{
public:
enum SampleType { Unknown, SignedInt, UnSignedInt, Float };
enum Endian { BigEndian = QSysInfo::BigEndian, LittleEndian = QSysInfo::LittleEndian };
QAudioFormat();
QAudioFormat(const QAudioFormat &other);
~QAudioFormat();
QAudioFormat& operator=(const QAudioFormat &other);
bool operator==(const QAudioFormat &other) const;
bool operator!=(const QAudioFormat &other) const;
bool isValid() const;
void setFrequency(int frequency);
int frequency() const;
void setSampleRate(int sampleRate);
int sampleRate() const;
void setChannels(int channels);
int channels() const;
void setChannelCount(int channelCount);
int channelCount() const;
void setSampleSize(int sampleSize);
int sampleSize() const;
void setCodec(const QString &codec);
QString codec() const;
void setByteOrder(QAudioFormat::Endian byteOrder);
QAudioFormat::Endian byteOrder() const;
void setSampleType(QAudioFormat::SampleType sampleType);
QAudioFormat::SampleType sampleType() const;
private:
QSharedDataPointer<QAudioFormatPrivate> d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOFORMAT_H

View File

@@ -0,0 +1,402 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudioinput.h"
#include "qaudiodevicefactory_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QAudioInput
\brief The QAudioInput class provides an interface for receiving audio data from an audio input device.
\inmodule QtMultimedia
\ingroup multimedia
\since 1.0
You can construct an audio input with the system's
\l{QAudioDeviceInfo::defaultInputDevice()}{default audio input
device}. It is also possible to create QAudioInput with a
specific QAudioDeviceInfo. When you create the audio input, you
should also send in the QAudioFormat to be used for the recording
(see the QAudioFormat class description for details).
To record to a file:
QAudioInput lets you record audio with an audio input device. The
default constructor of this class will use the systems default
audio device, but you can also specify a QAudioDeviceInfo for a
specific device. You also need to pass in the QAudioFormat in
which you wish to record.
Starting up the QAudioInput is simply a matter of calling start()
with a QIODevice opened for writing. For instance, to record to a
file, you can:
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input class members
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input setup
This will start recording if the format specified is supported by
the input device (you can check this with
QAudioDeviceInfo::isFormatSupported(). In case there are any
snags, use the error() function to check what went wrong. We stop
recording in the \c stopRecording() slot.
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input stop recording
At any point in time, QAudioInput will be in one of four states:
active, suspended, stopped, or idle. These states are specified by
the QAudio::State enum. You can request a state change directly through
suspend(), resume(), stop(), reset(), and start(). The current
state is reported by state(). QAudioOutput will also signal you
when the state changes (stateChanged()).
QAudioInput provides several ways of measuring the time that has
passed since the start() of the recording. The \c processedUSecs()
function returns the length of the stream in microseconds written,
i.e., it leaves out the times the audio input was suspended or idle.
The elapsedUSecs() function returns the time elapsed since start() was called regardless of
which states the QAudioInput has been in.
If an error should occur, you can fetch its reason with error().
The possible error reasons are described by the QAudio::Error
enum. The QAudioInput will enter the \l{QAudio::}{StoppedState} when
an error is encountered. Connect to the stateChanged() signal to
handle the error:
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input state changed
\sa QAudioOutput, QAudioDeviceInfo
*/
/*!
Construct a new audio input and attach it to \a parent.
The default audio input device is used with the output
\a format parameters.
\since 1.0
*/
QAudioInput::QAudioInput(const QAudioFormat &format, QObject *parent):
QObject(parent)
{
d = QAudioDeviceFactory::createDefaultInputDevice(format);
connect(d, SIGNAL(notify()), SIGNAL(notify()));
connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
}
/*!
Construct a new audio input and attach it to \a parent.
The device referenced by \a audioDevice is used with the input
\a format parameters.
\since 1.0
*/
QAudioInput::QAudioInput(const QAudioDeviceInfo &audioDevice, const QAudioFormat &format, QObject *parent):
QObject(parent)
{
d = QAudioDeviceFactory::createInputDevice(audioDevice, format);
connect(d, SIGNAL(notify()), SIGNAL(notify()));
connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
}
/*!
Destroy this audio input.
*/
QAudioInput::~QAudioInput()
{
delete d;
}
/*!
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 get audio data from the systems audio device the
state() is set to either QAudio::ActiveState or 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.
\since 1.0
\sa QIODevice
*/
void QAudioInput::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 read() 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.
\since 1.0
\sa QIODevice
*/
QIODevice* QAudioInput::start()
{
return d->start();
}
/*!
Returns the QAudioFormat being used.
\since 1.0
*/
QAudioFormat QAudioInput::format() const
{
return d->format();
}
/*!
Stops the audio input, detaching from the system resource.
Sets error() to QAudio::NoError, state() to QAudio::StoppedState and
emit stateChanged() signal.
\since 1.0
*/
void QAudioInput::stop()
{
d->stop();
}
/*!
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
void QAudioInput::reset()
{
d->reset();
}
/*!
Stops processing audio data, preserving buffered audio data.
Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
emit stateChanged() signal.
\since 1.0
*/
void QAudioInput::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.
\since 1.0
*/
void QAudioInput::resume()
{
d->resume();
}
/*!
Sets the audio buffer size to \a value milliseconds.
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, calling bufferSize() anytime after start()
will return the actual buffer size being used.
\since 1.0
*/
void QAudioInput::setBufferSize(int value)
{
d->setBufferSize(value);
}
/*!
Returns the audio buffer size in milliseconds.
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().
\since 1.0
*/
int QAudioInput::bufferSize() const
{
return d->bufferSize();
}
/*!
Returns the amount of audio data available to read in bytes.
NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState
state, otherwise returns zero.
\since 1.0
*/
int QAudioInput::bytesReady() const
{
/*
-If not ActiveState|IdleState, return 0
-return amount of audio data available to read
*/
return d->bytesReady();
}
/*!
Returns the period size in bytes.
Note: This is the recommended read size in bytes.
\since 1.0
*/
int QAudioInput::periodSize() const
{
return d->periodSize();
}
/*!
Sets the interval for notify() signal to be emitted.
This is based on the \a ms of audio data processed
not on actual real-time.
The minimum resolution of the timer is platform specific and values
should be checked with notifyInterval() to confirm actual value
being used.
\since 1.0
*/
void QAudioInput::setNotifyInterval(int ms)
{
d->setNotifyInterval(ms);
}
/*!
Returns the notify interval in milliseconds.
\since 1.0
*/
int QAudioInput::notifyInterval() const
{
return d->notifyInterval();
}
/*!
Returns the amount of audio data processed since start()
was called in microseconds.
\since 1.0
*/
qint64 QAudioInput::processedUSecs() const
{
return d->processedUSecs();
}
/*!
Returns the microseconds since start() was called, including time in Idle and
Suspend states.
\since 1.0
*/
qint64 QAudioInput::elapsedUSecs() const
{
return d->elapsedUSecs();
}
/*!
Returns the error state.
\since 1.0
*/
QAudio::Error QAudioInput::error() const
{
return d->error();
}
/*!
Returns the state of audio processing.
\since 1.0
*/
QAudio::State QAudioInput::state() const
{
return d->state();
}
/*!
\fn QAudioInput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
\since 1.0
*/
/*!
\fn QAudioInput::notify()
This signal is emitted when x ms of audio data has been processed
the interval set by setNotifyInterval(x).
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudioinput.cpp"

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOINPUT_H
#define QAUDIOINPUT_H
#include <QtCore/qiodevice.h>
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiodeviceinfo.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAbstractAudioInput;
class Q_MULTIMEDIA_EXPORT QAudioInput : public QObject
{
Q_OBJECT
public:
explicit QAudioInput(const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
explicit QAudioInput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
~QAudioInput();
QAudioFormat format() const;
void start(QIODevice *device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
void setBufferSize(int bytes);
int bufferSize() const;
int bytesReady() const;
int periodSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
Q_SIGNALS:
void stateChanged(QAudio::State);
void notify();
private:
Q_DISABLE_COPY(QAudioInput)
QAbstractAudioInput* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOINPUT_H

View File

@@ -0,0 +1,867 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <QtCore/qcoreapplication.h>
#include "qaudioinput_alsa_p.h"
#include "qaudiodeviceinfo_alsa_p.h"
QT_BEGIN_NAMESPACE
//#define DEBUG_AUDIO 1
QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device)
{
bytesAvailable = 0;
handle = 0;
ahandler = 0;
access = SND_PCM_ACCESS_RW_INTERLEAVED;
pcmformat = SND_PCM_FORMAT_S16;
buffer_size = 0;
period_size = 0;
buffer_time = 100000;
period_time = 20000;
totalTimeValue = 0;
intervalTime = 1000;
errorState = QAudio::NoError;
deviceState = QAudio::StoppedState;
audioSource = 0;
pullMode = true;
resuming = false;
m_device = device;
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),SLOT(userFeed()));
}
QAudioInputPrivate::~QAudioInputPrivate()
{
close();
disconnect(timer, SIGNAL(timeout()));
QCoreApplication::processEvents();
delete timer;
}
QAudio::Error QAudioInputPrivate::error() const
{
return errorState;
}
QAudio::State QAudioInputPrivate::state() const
{
return deviceState;
}
void QAudioInputPrivate::setFormat(const QAudioFormat& fmt)
{
if (deviceState == QAudio::StoppedState)
settings = fmt;
}
QAudioFormat QAudioInputPrivate::format() const
{
return settings;
}
int QAudioInputPrivate::xrun_recovery(int err)
{
int count = 0;
bool reset = false;
if(err == -EPIPE) {
errorState = QAudio::UnderrunError;
err = snd_pcm_prepare(handle);
if(err < 0)
reset = true;
else {
bytesAvailable = checkBytesReady();
if (bytesAvailable <= 0)
reset = true;
}
} else if((err == -ESTRPIPE)||(err == -EIO)) {
errorState = QAudio::IOError;
while((err = snd_pcm_resume(handle)) == -EAGAIN){
usleep(100);
count++;
if(count > 5) {
reset = true;
break;
}
}
if(err < 0) {
err = snd_pcm_prepare(handle);
if(err < 0)
reset = true;
}
}
if(reset) {
close();
open();
snd_pcm_prepare(handle);
return 0;
}
return err;
}
int QAudioInputPrivate::setFormat()
{
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
if(settings.sampleSize() == 8) {
format = SND_PCM_FORMAT_U8;
} else if(settings.sampleSize() == 16) {
if(settings.sampleType() == QAudioFormat::SignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_S16_LE;
else
format = SND_PCM_FORMAT_S16_BE;
} else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_U16_LE;
else
format = SND_PCM_FORMAT_U16_BE;
}
} else if(settings.sampleSize() == 24) {
if(settings.sampleType() == QAudioFormat::SignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_S24_LE;
else
format = SND_PCM_FORMAT_S24_BE;
} else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_U24_LE;
else
format = SND_PCM_FORMAT_U24_BE;
}
} else if(settings.sampleSize() == 32) {
if(settings.sampleType() == QAudioFormat::SignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_S32_LE;
else
format = SND_PCM_FORMAT_S32_BE;
} else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_U32_LE;
else
format = SND_PCM_FORMAT_U32_BE;
} else if(settings.sampleType() == QAudioFormat::Float) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_FLOAT_LE;
else
format = SND_PCM_FORMAT_FLOAT_BE;
}
} else if(settings.sampleSize() == 64) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
format = SND_PCM_FORMAT_FLOAT64_LE;
else
format = SND_PCM_FORMAT_FLOAT64_BE;
}
return format != SND_PCM_FORMAT_UNKNOWN
? snd_pcm_hw_params_set_format( handle, hwparams, format)
: -1;
}
void QAudioInputPrivate::start(QIODevice* device)
{
if(deviceState != QAudio::StoppedState)
close();
if(!pullMode && audioSource)
delete audioSource;
pullMode = true;
audioSource = device;
deviceState = QAudio::ActiveState;
if( !open() )
return;
emit stateChanged(deviceState);
}
QIODevice* QAudioInputPrivate::start()
{
if(deviceState != QAudio::StoppedState)
close();
if(!pullMode && audioSource)
delete audioSource;
pullMode = false;
audioSource = new InputPrivate(this);
audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
deviceState = QAudio::IdleState;
if( !open() )
return 0;
emit stateChanged(deviceState);
return audioSource;
}
void QAudioInputPrivate::stop()
{
if(deviceState == QAudio::StoppedState)
return;
deviceState = QAudio::StoppedState;
close();
emit stateChanged(deviceState);
}
bool QAudioInputPrivate::open()
{
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
clockStamp.restart();
timeStamp.restart();
elapsedTimeOffset = 0;
int dir;
int err = 0;
int count=0;
unsigned int freakuency=settings.frequency();
if (!settings.isValid()) {
qWarning("QAudioOutput: open error, invalid format.");
} else if (settings.sampleRate() <= 0) {
qWarning("QAudioOutput: open error, invalid sample rate (%d).",
settings.sampleRate());
} else {
err = -1;
}
if (err == 0) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit errorChanged(errorState);
return false;
}
QString dev = QString(QLatin1String(m_device.constData()));
QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioInput);
if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
if (devices.size() > 0)
dev = QLatin1String(devices.first());
else
return false;
#else
dev = QLatin1String("hw:0,0");
#endif
} else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = QLatin1String(m_device);
#else
int idx = 0;
char *name;
QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData());
while(snd_card_get_name(idx,&name) == 0) {
if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0)
break;
idx++;
}
dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
}
// Step 1: try and open the device
while((count < 5) && (err < 0)) {
err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
if(err < 0)
count++;
}
if (( err < 0)||(handle == 0)) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return false;
}
snd_pcm_nonblock( handle, 0 );
// Step 2: Set the desired HW parameters.
snd_pcm_hw_params_alloca( &hwparams );
bool fatal = false;
QString errMessage;
unsigned int chunks = 8;
err = snd_pcm_hw_params_any( handle, hwparams );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_any: err = %1").arg(err);
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_access( handle, hwparams, access );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_access: err = %1").arg(err);
}
}
if ( !fatal ) {
err = setFormat();
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_format: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_channels: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params(handle, hwparams);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params: err = %1").arg(err);
}
}
if( err < 0) {
qWarning()<<errMessage;
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return false;
}
snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
period_size = snd_pcm_frames_to_bytes(handle,period_frames);
snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);
// Step 3: Set the desired SW parameters.
snd_pcm_sw_params_t *swparams;
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_sw_params_current(handle, swparams);
snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames);
snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames);
snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames);
snd_pcm_sw_params(handle, swparams);
// Step 4: Prepare audio
ringBuffer.resize(buffer_size);
snd_pcm_prepare( handle );
snd_pcm_start(handle);
// Step 5: Setup timer
bytesAvailable = checkBytesReady();
if(pullMode)
connect(audioSource,SIGNAL(readyRead()),this,SLOT(userFeed()));
// Step 6: Start audio processing
chunks = buffer_size/period_size;
timer->start(period_time*chunks/2000);
errorState = QAudio::NoError;
totalTimeValue = 0;
return true;
}
void QAudioInputPrivate::close()
{
timer->stop();
if ( handle ) {
snd_pcm_drop( handle );
snd_pcm_close( handle );
handle = 0;
}
}
int QAudioInputPrivate::checkBytesReady()
{
if(resuming)
bytesAvailable = period_size;
else if(deviceState != QAudio::ActiveState
&& deviceState != QAudio::IdleState)
bytesAvailable = 0;
else {
int frames = snd_pcm_avail_update(handle);
if (frames < 0) {
bytesAvailable = frames;
} else {
if((int)frames > (int)buffer_frames)
frames = buffer_frames;
bytesAvailable = snd_pcm_frames_to_bytes(handle, frames);
}
}
return bytesAvailable;
}
int QAudioInputPrivate::bytesReady() const
{
return qMax(bytesAvailable, 0);
}
qint64 QAudioInputPrivate::read(char* data, qint64 len)
{
// Read in some audio data and write it to QIODevice, pull mode
if ( !handle )
return 0;
int bytesRead = 0;
int bytesInRingbufferBeforeRead = ringBuffer.bytesOfDataInBuffer();
if (ringBuffer.bytesOfDataInBuffer() < len) {
// bytesAvaiable is saved as a side effect of checkBytesReady().
int bytesToRead = checkBytesReady();
if (bytesToRead < 0) {
// bytesAvailable as negative is error code, try to recover from it.
xrun_recovery(bytesToRead);
bytesToRead = checkBytesReady();
if (bytesToRead < 0) {
// recovery failed must stop and set error.
close();
errorState = QAudio::IOError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return 0;
}
}
bytesToRead = qMin<qint64>(len, bytesToRead);
bytesToRead = qMin<qint64>(ringBuffer.freeBytes(), bytesToRead);
bytesToRead -= bytesToRead % period_size;
int count=0;
int err = 0;
while(count < 5 && bytesToRead > 0) {
char buffer[bytesToRead];
int chunks = bytesToRead / period_size;
int frames = chunks * period_frames;
if (frames > (int)buffer_frames)
frames = buffer_frames;
int readFrames = snd_pcm_readi(handle, buffer, frames);
if (readFrames >= 0) {
bytesRead = snd_pcm_frames_to_bytes(handle, readFrames);
ringBuffer.write(buffer, bytesRead);
#ifdef DEBUG_AUDIO
qDebug() << QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(bytesRead).arg(readFrames).toLatin1().constData();
#endif
break;
} else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
errorState = QAudio::IOError;
err = 0;
break;
} else {
if(readFrames == -EPIPE) {
errorState = QAudio::UnderrunError;
err = snd_pcm_prepare(handle);
} else if(readFrames == -ESTRPIPE) {
err = snd_pcm_prepare(handle);
}
if(err != 0) break;
}
count++;
}
}
bytesRead += bytesInRingbufferBeforeRead;
if (bytesRead > 0) {
// got some send it onward
#ifdef DEBUG_AUDIO
qDebug() << "frames to write to QIODevice = " <<
snd_pcm_bytes_to_frames( handle, (int)bytesRead ) << " (" << bytesRead << ") bytes";
#endif
if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return 0;
if (pullMode) {
qint64 l = 0;
qint64 bytesWritten = 0;
while (ringBuffer.bytesOfDataInBuffer() > 0) {
l = audioSource->write(ringBuffer.availableData(), ringBuffer.availableDataBlockSize());
if (l > 0) {
ringBuffer.readBytes(l);
bytesWritten += l;
} else {
break;
}
}
if (l < 0) {
close();
errorState = QAudio::IOError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
} else if (l == 0 && bytesWritten == 0) {
if (deviceState != QAudio::IdleState) {
errorState = QAudio::NoError;
deviceState = QAudio::IdleState;
emit stateChanged(deviceState);
}
} else {
bytesAvailable -= bytesWritten;
totalTimeValue += bytesWritten;
resuming = false;
if (deviceState != QAudio::ActiveState) {
errorState = QAudio::NoError;
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
}
return bytesWritten;
} else {
while (ringBuffer.bytesOfDataInBuffer() > 0) {
int size = ringBuffer.availableDataBlockSize();
memcpy(data, ringBuffer.availableData(), size);
data += size;
ringBuffer.readBytes(size);
}
bytesAvailable -= bytesRead;
totalTimeValue += bytesRead;
resuming = false;
if (deviceState != QAudio::ActiveState) {
errorState = QAudio::NoError;
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
return bytesRead;
}
}
return 0;
}
void QAudioInputPrivate::resume()
{
if(deviceState == QAudio::SuspendedState) {
int err = 0;
if(handle) {
err = snd_pcm_prepare( handle );
if(err < 0)
xrun_recovery(err);
err = snd_pcm_start(handle);
if(err < 0)
xrun_recovery(err);
bytesAvailable = buffer_size;
}
resuming = true;
deviceState = QAudio::ActiveState;
int chunks = buffer_size/period_size;
timer->start(period_time*chunks/2000);
emit stateChanged(deviceState);
}
}
void QAudioInputPrivate::setBufferSize(int value)
{
buffer_size = value;
}
int QAudioInputPrivate::bufferSize() const
{
return buffer_size;
}
int QAudioInputPrivate::periodSize() const
{
return period_size;
}
void QAudioInputPrivate::setNotifyInterval(int ms)
{
intervalTime = qMax(0, ms);
}
int QAudioInputPrivate::notifyInterval() const
{
return intervalTime;
}
qint64 QAudioInputPrivate::processedUSecs() const
{
qint64 result = qint64(1000000) * totalTimeValue /
(settings.channels()*(settings.sampleSize()/8)) /
settings.frequency();
return result;
}
void QAudioInputPrivate::suspend()
{
if(deviceState == QAudio::ActiveState||resuming) {
timer->stop();
deviceState = QAudio::SuspendedState;
emit stateChanged(deviceState);
}
}
void QAudioInputPrivate::userFeed()
{
if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState)
return;
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :userFeed() IN";
#endif
deviceReady();
}
bool QAudioInputPrivate::deviceReady()
{
if(pullMode) {
// reads some audio data and writes it to QIODevice
read(0, buffer_size);
} else {
// emits readyRead() so user will call read() on QIODevice to get some audio data
InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
a->trigger();
}
bytesAvailable = checkBytesReady();
if(deviceState != QAudio::ActiveState)
return true;
if (bytesAvailable < 0) {
// bytesAvailable as negative is error code, try to recover from it.
xrun_recovery(bytesAvailable);
bytesAvailable = checkBytesReady();
if (bytesAvailable < 0) {
// recovery failed must stop and set error.
close();
errorState = QAudio::IOError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return 0;
}
}
if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
emit notify();
elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
timeStamp.restart();
}
return true;
}
qint64 QAudioInputPrivate::elapsedUSecs() const
{
if (deviceState == QAudio::StoppedState)
return 0;
return clockStamp.elapsed()*1000;
}
void QAudioInputPrivate::reset()
{
if(handle)
snd_pcm_reset(handle);
stop();
bytesAvailable = 0;
}
void QAudioInputPrivate::drain()
{
if(handle)
snd_pcm_drain(handle);
}
InputPrivate::InputPrivate(QAudioInputPrivate* audio)
{
audioDevice = qobject_cast<QAudioInputPrivate*>(audio);
}
InputPrivate::~InputPrivate()
{
}
qint64 InputPrivate::readData( char* data, qint64 len)
{
return audioDevice->read(data,len);
}
qint64 InputPrivate::writeData(const char* data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)
return 0;
}
void InputPrivate::trigger()
{
emit readyRead();
}
RingBuffer::RingBuffer() :
m_head(0),
m_tail(0)
{
}
void RingBuffer::resize(int size)
{
m_data.resize(size);
}
int RingBuffer::bytesOfDataInBuffer() const
{
if (m_head < m_tail)
return m_tail - m_head;
else if (m_tail < m_head)
return m_data.size() + m_tail - m_head;
else
return 0;
}
int RingBuffer::freeBytes() const
{
if (m_head > m_tail)
return m_head - m_tail - 1;
else if (m_tail > m_head)
return m_data.size() - m_tail + m_head - 1;
else
return m_data.size() - 1;
}
const char *RingBuffer::availableData() const
{
return (m_data.constData() + m_head);
}
int RingBuffer::availableDataBlockSize() const
{
if (m_head > m_tail)
return m_data.size() - m_head;
else if (m_tail > m_head)
return m_tail - m_head;
else
return 0;
}
void RingBuffer::readBytes(int bytes)
{
m_head = (m_head + bytes) % m_data.size();
}
void RingBuffer::write(char *data, int len)
{
if (m_tail + len < m_data.size()) {
memcpy(m_data.data() + m_tail, data, len);
m_tail += len;
} else {
int bytesUntilEnd = m_data.size() - m_tail;
memcpy(m_data.data() + m_tail, data, bytesUntilEnd);
if (len - bytesUntilEnd > 0)
memcpy(m_data.data(), data + bytesUntilEnd, len - bytesUntilEnd);
m_tail = len - bytesUntilEnd;
}
}
QT_END_NAMESPACE
#include "moc_qaudioinput_alsa_p.cpp"

View File

@@ -0,0 +1,191 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUTALSA_H
#define QAUDIOINPUTALSA_H
#include <alsa/asoundlib.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class InputPrivate;
class RingBuffer
{
public:
RingBuffer();
void resize(int size);
int bytesOfDataInBuffer() const;
int freeBytes() const;
const char *availableData() const;
int availableDataBlockSize() const;
void readBytes(int bytes);
void write(char *data, int len);
private:
int m_head;
int m_tail;
QByteArray m_data;
};
class QAudioInputPrivate : public QAbstractAudioInput
{
Q_OBJECT
public:
QAudioInputPrivate(const QByteArray &device);
~QAudioInputPrivate();
qint64 read(char* data, qint64 len);
void start(QIODevice* device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
bool resuming;
snd_pcm_t* handle;
qint64 totalTimeValue;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private slots:
void userFeed();
bool deviceReady();
private:
int checkBytesReady();
int xrun_recovery(int err);
int setFormat();
bool open();
void close();
void drain();
QTimer* timer;
QTime timeStamp;
QTime clockStamp;
qint64 elapsedTimeOffset;
int intervalTime;
RingBuffer ringBuffer;
int bytesAvailable;
QByteArray m_device;
bool pullMode;
int buffer_size;
int period_size;
unsigned int buffer_time;
unsigned int period_time;
snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames;
snd_async_handler_t* ahandler;
snd_pcm_access_t access;
snd_pcm_format_t pcmformat;
snd_timestamp_t* timestamp;
snd_pcm_hw_params_t *hwparams;
};
class InputPrivate : public QIODevice
{
Q_OBJECT
public:
InputPrivate(QAudioInputPrivate* audio);
~InputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
void trigger();
private:
QAudioInputPrivate *audioDevice;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,989 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <QtCore/qendian.h>
#include <QtCore/qtimer.h>
#include <QtCore/qdebug.h>
#include <qaudioinput.h>
#include "qaudio_mac_p.h"
#include "qaudioinput_mac_p.h"
#include "qaudiodeviceinfo_mac_p.h"
QT_BEGIN_NAMESPACE
namespace QtMultimediaInternal
{
static const int default_buffer_size = 4 * 1024;
class QAudioBufferList
{
public:
QAudioBufferList(AudioStreamBasicDescription const& streamFormat):
owner(false),
sf(streamFormat)
{
const bool isInterleaved = (sf.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
const int numberOfBuffers = isInterleaved ? 1 : sf.mChannelsPerFrame;
dataSize = 0;
bfs = reinterpret_cast<AudioBufferList*>(qMalloc(sizeof(AudioBufferList) +
(sizeof(AudioBuffer) * numberOfBuffers)));
bfs->mNumberBuffers = numberOfBuffers;
for (int i = 0; i < numberOfBuffers; ++i) {
bfs->mBuffers[i].mNumberChannels = isInterleaved ? numberOfBuffers : 1;
bfs->mBuffers[i].mDataByteSize = 0;
bfs->mBuffers[i].mData = 0;
}
}
QAudioBufferList(AudioStreamBasicDescription const& streamFormat, char* buffer, int bufferSize):
owner(false),
sf(streamFormat),
bfs(0)
{
dataSize = bufferSize;
bfs = reinterpret_cast<AudioBufferList*>(qMalloc(sizeof(AudioBufferList) + sizeof(AudioBuffer)));
bfs->mNumberBuffers = 1;
bfs->mBuffers[0].mNumberChannels = 1;
bfs->mBuffers[0].mDataByteSize = dataSize;
bfs->mBuffers[0].mData = buffer;
}
QAudioBufferList(AudioStreamBasicDescription const& streamFormat, int framesToBuffer):
owner(true),
sf(streamFormat),
bfs(0)
{
const bool isInterleaved = (sf.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
const int numberOfBuffers = isInterleaved ? 1 : sf.mChannelsPerFrame;
dataSize = framesToBuffer * sf.mBytesPerFrame;
bfs = reinterpret_cast<AudioBufferList*>(qMalloc(sizeof(AudioBufferList) +
(sizeof(AudioBuffer) * numberOfBuffers)));
bfs->mNumberBuffers = numberOfBuffers;
for (int i = 0; i < numberOfBuffers; ++i) {
bfs->mBuffers[i].mNumberChannels = isInterleaved ? numberOfBuffers : 1;
bfs->mBuffers[i].mDataByteSize = dataSize;
bfs->mBuffers[i].mData = qMalloc(dataSize);
}
}
~QAudioBufferList()
{
if (owner) {
for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i)
qFree(bfs->mBuffers[i].mData);
}
qFree(bfs);
}
AudioBufferList* audioBufferList() const
{
return bfs;
}
char* data(int buffer = 0) const
{
return static_cast<char*>(bfs->mBuffers[buffer].mData);
}
qint64 bufferSize(int buffer = 0) const
{
return bfs->mBuffers[buffer].mDataByteSize;
}
int frameCount(int buffer = 0) const
{
return bfs->mBuffers[buffer].mDataByteSize / sf.mBytesPerFrame;
}
int packetCount(int buffer = 0) const
{
return bfs->mBuffers[buffer].mDataByteSize / sf.mBytesPerPacket;
}
int packetSize() const
{
return sf.mBytesPerPacket;
}
void reset()
{
for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) {
bfs->mBuffers[i].mDataByteSize = dataSize;
bfs->mBuffers[i].mData = 0;
}
}
private:
bool owner;
int dataSize;
AudioStreamBasicDescription sf;
AudioBufferList* bfs;
};
class QAudioPacketFeeder
{
public:
QAudioPacketFeeder(QAudioBufferList* abl):
audioBufferList(abl)
{
totalPackets = audioBufferList->packetCount();
position = 0;
}
bool feed(AudioBufferList& dst, UInt32& packetCount)
{
if (position == totalPackets) {
dst.mBuffers[0].mDataByteSize = 0;
packetCount = 0;
return false;
}
if (totalPackets - position < packetCount)
packetCount = totalPackets - position;
dst.mBuffers[0].mDataByteSize = packetCount * audioBufferList->packetSize();
dst.mBuffers[0].mData = audioBufferList->data() + (position * audioBufferList->packetSize());
position += packetCount;
return true;
}
bool empty() const
{
return position == totalPackets;
}
private:
UInt32 totalPackets;
UInt32 position;
QAudioBufferList* audioBufferList;
};
class QAudioInputBuffer : public QObject
{
Q_OBJECT
public:
QAudioInputBuffer(int bufferSize,
int maxPeriodSize,
AudioStreamBasicDescription const& inputFormat,
AudioStreamBasicDescription const& outputFormat,
QObject* parent):
QObject(parent),
m_deviceError(false),
m_audioConverter(0),
m_inputFormat(inputFormat),
m_outputFormat(outputFormat)
{
m_maxPeriodSize = maxPeriodSize;
m_periodTime = m_maxPeriodSize / m_outputFormat.mBytesPerFrame * 1000 / m_outputFormat.mSampleRate;
m_buffer = new QAudioRingBuffer(bufferSize + (bufferSize % maxPeriodSize == 0 ? 0 : maxPeriodSize - (bufferSize % maxPeriodSize)));
m_inputBufferList = new QAudioBufferList(m_inputFormat);
m_flushTimer = new QTimer(this);
connect(m_flushTimer, SIGNAL(timeout()), SLOT(flushBuffer()));
if (toQAudioFormat(inputFormat) != toQAudioFormat(outputFormat)) {
if (AudioConverterNew(&m_inputFormat, &m_outputFormat, &m_audioConverter) != noErr) {
qWarning() << "QAudioInput: Unable to create an Audio Converter";
m_audioConverter = 0;
}
}
}
~QAudioInputBuffer()
{
delete m_buffer;
}
qint64 renderFromDevice(AudioUnit audioUnit,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames)
{
const bool pullMode = m_device == 0;
OSStatus err;
qint64 framesRendered = 0;
m_inputBufferList->reset();
err = AudioUnitRender(audioUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
m_inputBufferList->audioBufferList());
if (m_audioConverter != 0) {
QAudioPacketFeeder feeder(m_inputBufferList);
int copied = 0;
const int available = m_buffer->free();
while (err == noErr && !feeder.empty()) {
QAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(available);
if (region.second == 0)
break;
AudioBufferList output;
output.mNumberBuffers = 1;
output.mBuffers[0].mNumberChannels = 1;
output.mBuffers[0].mDataByteSize = region.second;
output.mBuffers[0].mData = region.first;
UInt32 packetSize = region.second / m_outputFormat.mBytesPerPacket;
err = AudioConverterFillComplexBuffer(m_audioConverter,
converterCallback,
&feeder,
&packetSize,
&output,
0);
region.second = output.mBuffers[0].mDataByteSize;
copied += region.second;
m_buffer->releaseWriteRegion(region);
}
framesRendered += copied / m_outputFormat.mBytesPerFrame;
}
else {
const int available = m_inputBufferList->bufferSize();
bool wecan = true;
int copied = 0;
while (wecan && copied < available) {
QAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(available - copied);
if (region.second > 0) {
memcpy(region.first, m_inputBufferList->data() + copied, region.second);
copied += region.second;
}
else
wecan = false;
m_buffer->releaseWriteRegion(region);
}
framesRendered = copied / m_outputFormat.mBytesPerFrame;
}
if (pullMode && framesRendered > 0)
emit readyRead();
return framesRendered;
}
qint64 readBytes(char* data, qint64 len)
{
bool wecan = true;
qint64 bytesCopied = 0;
len -= len % m_maxPeriodSize;
while (wecan && bytesCopied < len) {
QAudioRingBuffer::Region region = m_buffer->acquireReadRegion(len - bytesCopied);
if (region.second > 0) {
memcpy(data + bytesCopied, region.first, region.second);
bytesCopied += region.second;
}
else
wecan = false;
m_buffer->releaseReadRegion(region);
}
return bytesCopied;
}
void setFlushDevice(QIODevice* device)
{
if (m_device != device)
m_device = device;
}
void startFlushTimer()
{
if (m_device != 0) {
m_flushTimer->start((m_buffer->size() - (m_maxPeriodSize * 2)) / m_maxPeriodSize * m_periodTime);
}
}
void stopFlushTimer()
{
m_flushTimer->stop();
}
void flush(bool all = false)
{
if (m_device == 0)
return;
const int used = m_buffer->used();
const int readSize = all ? used : used - (used % m_maxPeriodSize);
if (readSize > 0) {
bool wecan = true;
int flushed = 0;
while (!m_deviceError && wecan && flushed < readSize) {
QAudioRingBuffer::Region region = m_buffer->acquireReadRegion(readSize - flushed);
if (region.second > 0) {
int bytesWritten = m_device->write(region.first, region.second);
if (bytesWritten < 0) {
stopFlushTimer();
m_deviceError = true;
}
else {
region.second = bytesWritten;
flushed += bytesWritten;
wecan = bytesWritten != 0;
}
}
else
wecan = false;
m_buffer->releaseReadRegion(region);
}
}
}
void reset()
{
m_buffer->reset();
m_deviceError = false;
}
int available() const
{
return m_buffer->free();
}
int used() const
{
return m_buffer->used();
}
signals:
void readyRead();
private slots:
void flushBuffer()
{
flush();
}
private:
bool m_deviceError;
int m_maxPeriodSize;
int m_periodTime;
QIODevice* m_device;
QTimer* m_flushTimer;
QAudioRingBuffer* m_buffer;
QAudioBufferList* m_inputBufferList;
AudioConverterRef m_audioConverter;
AudioStreamBasicDescription m_inputFormat;
AudioStreamBasicDescription m_outputFormat;
const static OSStatus as_empty = 'qtem';
// Converter callback
static OSStatus converterCallback(AudioConverterRef inAudioConverter,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription** outDataPacketDescription,
void* inUserData)
{
Q_UNUSED(inAudioConverter);
Q_UNUSED(outDataPacketDescription);
QAudioPacketFeeder* feeder = static_cast<QAudioPacketFeeder*>(inUserData);
if (!feeder->feed(*ioData, *ioNumberDataPackets))
return as_empty;
return noErr;
}
};
class MacInputDevice : public QIODevice
{
Q_OBJECT
public:
MacInputDevice(QAudioInputBuffer* audioBuffer, QObject* parent):
QIODevice(parent),
m_audioBuffer(audioBuffer)
{
open(QIODevice::ReadOnly | QIODevice::Unbuffered);
connect(m_audioBuffer, SIGNAL(readyRead()), SIGNAL(readyRead()));
}
qint64 readData(char* data, qint64 len)
{
return m_audioBuffer->readBytes(data, len);
}
qint64 writeData(const char* data, qint64 len)
{
Q_UNUSED(data);
Q_UNUSED(len);
return 0;
}
bool isSequential() const
{
return true;
}
private:
QAudioInputBuffer* m_audioBuffer;
};
}
QAudioInputPrivate::QAudioInputPrivate(const QByteArray& device)
{
QDataStream ds(device);
quint32 did, mode;
ds >> did >> mode;
if (QAudio::Mode(mode) == QAudio::AudioOutput)
errorCode = QAudio::OpenError;
else {
audioDeviceInfo = new QAudioDeviceInfoInternal(device, QAudio::AudioInput);
isOpen = false;
audioDeviceId = AudioDeviceID(did);
audioUnit = 0;
startTime = 0;
totalFrames = 0;
audioBuffer = 0;
internalBufferSize = QtMultimediaInternal::default_buffer_size;
clockFrequency = AudioGetHostClockFrequency() / 1000;
errorCode = QAudio::NoError;
stateCode = QAudio::StoppedState;
intervalTimer = new QTimer(this);
intervalTimer->setInterval(1000);
connect(intervalTimer, SIGNAL(timeout()), SIGNAL(notify()));
}
}
QAudioInputPrivate::~QAudioInputPrivate()
{
close();
delete audioDeviceInfo;
}
bool QAudioInputPrivate::open()
{
UInt32 size = 0;
if (isOpen)
return true;
ComponentDescription cd;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_HALOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
// Open
Component cp = FindNextComponent(NULL, &cd);
if (cp == 0) {
qWarning() << "QAudioInput: Failed to find HAL Output component";
return false;
}
if (OpenAComponent(cp, &audioUnit) != noErr) {
qWarning() << "QAudioInput: Unable to Open Output Component";
return false;
}
// Set mode
// switch to input mode
UInt32 enable = 1;
if (AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
1,
&enable,
sizeof(enable)) != noErr) {
qWarning() << "QAudioInput: Unable to switch to input mode (Enable Input)";
return false;
}
enable = 0;
if (AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
0,
&enable,
sizeof(enable)) != noErr) {
qWarning() << "QAudioInput: Unable to switch to input mode (Disable output)";
return false;
}
// register callback
AURenderCallbackStruct cb;
cb.inputProc = inputCallback;
cb.inputProcRefCon = this;
if (AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
0,
&cb,
sizeof(cb)) != noErr) {
qWarning() << "QAudioInput: Failed to set AudioUnit callback";
return false;
}
// Set Audio Device
if (AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&audioDeviceId,
sizeof(audioDeviceId)) != noErr) {
qWarning() << "QAudioInput: Unable to use configured device";
return false;
}
// Set format
// Wanted
streamFormat = toAudioStreamBasicDescription(audioFormat);
// Required on unit
if (audioFormat == audioDeviceInfo->preferredFormat()) {
deviceFormat = streamFormat;
AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&deviceFormat,
sizeof(deviceFormat));
}
else {
size = sizeof(deviceFormat);
if (AudioUnitGetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
1,
&deviceFormat,
&size) != noErr) {
qWarning() << "QAudioInput: Unable to retrieve device format";
return false;
}
if (AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&deviceFormat,
sizeof(deviceFormat)) != noErr) {
qWarning() << "QAudioInput: Unable to set device format";
return false;
}
}
// Setup buffers
UInt32 numberOfFrames;
size = sizeof(UInt32);
if (AudioUnitGetProperty(audioUnit,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
0,
&numberOfFrames,
&size) != noErr) {
qWarning() << "QAudioInput: Failed to get audio period size";
return false;
}
// Allocate buffer
periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame;
if (internalBufferSize < periodSizeBytes * 2)
internalBufferSize = periodSizeBytes * 2;
else
internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
audioBuffer = new QtMultimediaInternal::QAudioInputBuffer(internalBufferSize,
periodSizeBytes,
deviceFormat,
streamFormat,
this);
audioIO = new QtMultimediaInternal::MacInputDevice(audioBuffer, this);
// Init
if (AudioUnitInitialize(audioUnit) != noErr) {
qWarning() << "QAudioInput: Failed to initialize AudioUnit";
return false;
}
isOpen = true;
return isOpen;
}
void QAudioInputPrivate::close()
{
if (audioUnit != 0) {
AudioOutputUnitStop(audioUnit);
AudioUnitUninitialize(audioUnit);
CloseComponent(audioUnit);
}
delete audioBuffer;
}
QAudioFormat QAudioInputPrivate::format() const
{
return audioFormat;
}
void QAudioInputPrivate::setFormat(const QAudioFormat& fmt)
{
if (stateCode == QAudio::StoppedState)
audioFormat = fmt;
}
void QAudioInputPrivate::start(QIODevice* device)
{
QIODevice* op = device;
if (!audioDeviceInfo->isFormatSupported(audioFormat) || !open()) {
stateCode = QAudio::StoppedState;
errorCode = QAudio::OpenError;
return;
}
reset();
audioBuffer->reset();
audioBuffer->setFlushDevice(op);
if (op == 0)
op = audioIO;
// Start
startTime = AudioGetCurrentHostTime();
totalFrames = 0;
audioThreadStart();
stateCode = QAudio::ActiveState;
errorCode = QAudio::NoError;
emit stateChanged(stateCode);
}
QIODevice* QAudioInputPrivate::start()
{
QIODevice* op = 0;
if (!audioDeviceInfo->isFormatSupported(audioFormat) || !open()) {
stateCode = QAudio::StoppedState;
errorCode = QAudio::OpenError;
return audioIO;
}
reset();
audioBuffer->reset();
audioBuffer->setFlushDevice(op);
if (op == 0)
op = audioIO;
// Start
startTime = AudioGetCurrentHostTime();
totalFrames = 0;
audioThreadStart();
stateCode = QAudio::ActiveState;
errorCode = QAudio::NoError;
emit stateChanged(stateCode);
return op;
}
void QAudioInputPrivate::stop()
{
QMutexLocker lock(&mutex);
if (stateCode != QAudio::StoppedState) {
audioThreadStop();
audioBuffer->flush(true);
errorCode = QAudio::NoError;
stateCode = QAudio::StoppedState;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioInputPrivate::reset()
{
QMutexLocker lock(&mutex);
if (stateCode != QAudio::StoppedState) {
audioThreadStop();
errorCode = QAudio::NoError;
stateCode = QAudio::StoppedState;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioInputPrivate::suspend()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState || stateCode == QAudio::IdleState) {
audioThreadStop();
errorCode = QAudio::NoError;
stateCode = QAudio::SuspendedState;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioInputPrivate::resume()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::SuspendedState) {
audioThreadStart();
errorCode = QAudio::NoError;
stateCode = QAudio::ActiveState;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
int QAudioInputPrivate::bytesReady() const
{
return audioBuffer->used();
}
int QAudioInputPrivate::periodSize() const
{
return periodSizeBytes;
}
void QAudioInputPrivate::setBufferSize(int bs)
{
internalBufferSize = bs;
}
int QAudioInputPrivate::bufferSize() const
{
return internalBufferSize;
}
void QAudioInputPrivate::setNotifyInterval(int milliSeconds)
{
if (intervalTimer->interval() == milliSeconds)
return;
if (milliSeconds <= 0)
milliSeconds = 0;
intervalTimer->setInterval(milliSeconds);
}
int QAudioInputPrivate::notifyInterval() const
{
return intervalTimer->interval();
}
qint64 QAudioInputPrivate::processedUSecs() const
{
return totalFrames * 1000000 / audioFormat.frequency();
}
qint64 QAudioInputPrivate::elapsedUSecs() const
{
if (stateCode == QAudio::StoppedState)
return 0;
return (AudioGetCurrentHostTime() - startTime) / (clockFrequency / 1000);
}
QAudio::Error QAudioInputPrivate::error() const
{
return errorCode;
}
QAudio::State QAudioInputPrivate::state() const
{
return stateCode;
}
void QAudioInputPrivate::audioThreadStop()
{
stopTimers();
if (audioThreadState.testAndSetAcquire(Running, Stopped))
threadFinished.wait(&mutex);
}
void QAudioInputPrivate::audioThreadStart()
{
startTimers();
audioThreadState = Running;
AudioOutputUnitStart(audioUnit);
}
void QAudioInputPrivate::audioDeviceStop()
{
AudioOutputUnitStop(audioUnit);
audioThreadState = Stopped;
threadFinished.wakeOne();
}
void QAudioInputPrivate::audioDeviceFull()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState) {
audioDeviceStop();
errorCode = QAudio::UnderrunError;
stateCode = QAudio::IdleState;
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
}
void QAudioInputPrivate::audioDeviceError()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState) {
audioDeviceStop();
errorCode = QAudio::IOError;
stateCode = QAudio::StoppedState;
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
}
void QAudioInputPrivate::startTimers()
{
audioBuffer->startFlushTimer();
if (intervalTimer->interval() > 0)
intervalTimer->start();
}
void QAudioInputPrivate::stopTimers()
{
audioBuffer->stopFlushTimer();
intervalTimer->stop();
}
void QAudioInputPrivate::deviceStopped()
{
stopTimers();
emit stateChanged(stateCode);
}
// Input callback
OSStatus QAudioInputPrivate::inputCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData)
{
Q_UNUSED(ioData);
QAudioInputPrivate* d = static_cast<QAudioInputPrivate*>(inRefCon);
const int threadState = d->audioThreadState.fetchAndAddAcquire(0);
if (threadState == Stopped)
d->audioDeviceStop();
else {
qint64 framesWritten;
framesWritten = d->audioBuffer->renderFromDevice(d->audioUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames);
if (framesWritten > 0)
d->totalFrames += framesWritten;
else if (framesWritten == 0)
d->audioDeviceFull();
else if (framesWritten < 0)
d->audioDeviceError();
}
return noErr;
}
QT_END_NAMESPACE
#include "qaudioinput_mac_p.moc"

View File

@@ -0,0 +1,174 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUT_MAC_P_H
#define QAUDIOINPUT_MAC_P_H
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QtCore/qobject.h>
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
#include <QtCore/qatomic.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QTimer;
class QIODevice;
class QAbstractAudioDeviceInfo;
namespace QtMultimediaInternal
{
class QAudioInputBuffer;
}
class QAudioInputPrivate : public QAbstractAudioInput
{
Q_OBJECT
public:
bool isOpen;
int periodSizeBytes;
int internalBufferSize;
qint64 totalFrames;
QAudioFormat audioFormat;
QIODevice* audioIO;
AudioUnit audioUnit;
AudioDeviceID audioDeviceId;
Float64 clockFrequency;
UInt64 startTime;
QAudio::Error errorCode;
QAudio::State stateCode;
QtMultimediaInternal::QAudioInputBuffer* audioBuffer;
QMutex mutex;
QWaitCondition threadFinished;
QAtomicInt audioThreadState;
QTimer* intervalTimer;
AudioStreamBasicDescription streamFormat;
AudioStreamBasicDescription deviceFormat;
QAbstractAudioDeviceInfo *audioDeviceInfo;
QAudioInputPrivate(const QByteArray& device);
~QAudioInputPrivate();
bool open();
void close();
QAudioFormat format() const;
void setFormat(const QAudioFormat& fmt);
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
void idle();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void audioThreadStart();
void audioThreadStop();
void audioDeviceStop();
void audioDeviceFull();
void audioDeviceError();
void startTimers();
void stopTimers();
private slots:
void deviceStopped();
private:
enum { Running, Stopped };
// Input callback
static OSStatus inputCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOINPUT_MAC_P_H

View File

@@ -0,0 +1,642 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qaudioinput_win32_p.h"
QT_BEGIN_NAMESPACE
//#define DEBUG_AUDIO 1
QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device)
{
bytesAvailable = 0;
buffer_size = 0;
period_size = 0;
m_device = device;
totalTimeValue = 0;
intervalTime = 1000;
errorState = QAudio::NoError;
deviceState = QAudio::StoppedState;
audioSource = 0;
pullMode = true;
resuming = false;
finished = false;
waveBlockOffset = 0;
}
QAudioInputPrivate::~QAudioInputPrivate()
{
stop();
}
void QT_WIN_CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
Q_UNUSED(dwParam1)
Q_UNUSED(dwParam2)
Q_UNUSED(hWaveIn)
QAudioInputPrivate* qAudio;
qAudio = (QAudioInputPrivate*)(dwInstance);
if(!qAudio)
return;
QMutexLocker(&qAudio->mutex);
switch(uMsg) {
case WIM_OPEN:
break;
case WIM_DATA:
if(qAudio->waveFreeBlockCount > 0)
qAudio->waveFreeBlockCount--;
qAudio->feedback();
break;
case WIM_CLOSE:
qAudio->finished = true;
break;
default:
return;
}
}
WAVEHDR* QAudioInputPrivate::allocateBlocks(int size, int count)
{
int i;
unsigned char* buffer;
WAVEHDR* blocks;
DWORD totalBufferSize = (size + sizeof(WAVEHDR))*count;
if((buffer=(unsigned char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
totalBufferSize)) == 0) {
qWarning("QAudioInput: Memory allocation error");
return 0;
}
blocks = (WAVEHDR*)buffer;
buffer += sizeof(WAVEHDR)*count;
for(i = 0; i < count; i++) {
blocks[i].dwBufferLength = size;
blocks[i].lpData = (LPSTR)buffer;
blocks[i].dwBytesRecorded=0;
blocks[i].dwUser = 0L;
blocks[i].dwFlags = 0L;
blocks[i].dwLoops = 0L;
result = waveInPrepareHeader(hWaveIn,&blocks[i], sizeof(WAVEHDR));
if(result != MMSYSERR_NOERROR) {
qWarning("QAudioInput: Can't prepare block %d",i);
return 0;
}
buffer += size;
}
return blocks;
}
void QAudioInputPrivate::freeBlocks(WAVEHDR* blockArray)
{
WAVEHDR* blocks = blockArray;
int count = buffer_size/period_size;
for(int i = 0; i < count; i++) {
waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR));
blocks++;
}
HeapFree(GetProcessHeap(), 0, blockArray);
}
QAudio::Error QAudioInputPrivate::error() const
{
return errorState;
}
QAudio::State QAudioInputPrivate::state() const
{
return deviceState;
}
void QAudioInputPrivate::setFormat(const QAudioFormat& fmt)
{
if (deviceState == QAudio::StoppedState)
settings = fmt;
}
QAudioFormat QAudioInputPrivate::format() const
{
return settings;
}
void QAudioInputPrivate::start(QIODevice* device)
{
if(deviceState != QAudio::StoppedState)
close();
if(!pullMode && audioSource)
delete audioSource;
pullMode = true;
audioSource = device;
deviceState = QAudio::ActiveState;
if(!open())
return;
emit stateChanged(deviceState);
}
QIODevice* QAudioInputPrivate::start()
{
if(deviceState != QAudio::StoppedState)
close();
if(!pullMode && audioSource)
delete audioSource;
pullMode = false;
audioSource = new InputPrivate(this);
audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
deviceState = QAudio::IdleState;
if(!open())
return 0;
emit stateChanged(deviceState);
return audioSource;
}
void QAudioInputPrivate::stop()
{
if(deviceState == QAudio::StoppedState)
return;
close();
emit stateChanged(deviceState);
}
bool QAudioInputPrivate::open()
{
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
header = 0;
period_size = 0;
if (!settings.isValid()) {
qWarning("QAudioInput: open error, invalid format.");
} else if (settings.channelCount() <= 0) {
qWarning("QAudioInput: open error, invalid number of channels (%d).",
settings.channelCount());
} else if (settings.sampleSize() <= 0) {
qWarning("QAudioInput: open error, invalid sample size (%d).",
settings.sampleSize());
} else if (settings.frequency() < 8000 || settings.frequency() > 48000) {
qWarning("QAudioInput: open error, frequency out of range (%d).", settings.frequency());
} else if (buffer_size == 0) {
buffer_size
= (settings.frequency()
* settings.channelCount()
* settings.sampleSize()
+ 39) / 40;
period_size = buffer_size / 5;
} else {
period_size = buffer_size / 5;
}
if (period_size == 0) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return false;
}
timeStamp.restart();
elapsedTimeOffset = 0;
wfx.nSamplesPerSec = settings.frequency();
wfx.wBitsPerSample = settings.sampleSize();
wfx.nChannels = settings.channels();
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
QDataStream ds(&m_device, QIODevice::ReadOnly);
quint32 deviceId;
ds >> deviceId;
if (waveInOpen(&hWaveIn, UINT_PTR(deviceId), &wfx,
(DWORD_PTR)&waveInProc,
(DWORD_PTR) this,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
qWarning("QAudioInput: failed to open audio device");
return false;
}
waveBlocks = allocateBlocks(period_size, buffer_size/period_size);
waveBlockOffset = 0;
if(waveBlocks == 0) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
qWarning("QAudioInput: failed to allocate blocks. open failed");
return false;
}
mutex.lock();
waveFreeBlockCount = buffer_size/period_size;
mutex.unlock();
for(int i=0; i<buffer_size/period_size; i++) {
result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR));
if(result != MMSYSERR_NOERROR) {
qWarning("QAudioInput: failed to setup block %d,err=%d",i,result);
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return false;
}
}
result = waveInStart(hWaveIn);
if(result) {
qWarning("QAudioInput: failed to start audio input");
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return false;
}
timeStampOpened.restart();
elapsedTimeOffset = 0;
totalTimeValue = 0;
errorState = QAudio::NoError;
return true;
}
void QAudioInputPrivate::close()
{
if(deviceState == QAudio::StoppedState)
return;
deviceState = QAudio::StoppedState;
waveInReset(hWaveIn);
waveInClose(hWaveIn);
int count = 0;
while(!finished && count < 500) {
count++;
Sleep(10);
}
mutex.lock();
for(int i=0; i<waveFreeBlockCount; i++)
waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR));
freeBlocks(waveBlocks);
mutex.unlock();
}
int QAudioInputPrivate::bytesReady() const
{
if(period_size == 0 || buffer_size == 0)
return 0;
int buf = ((buffer_size/period_size)-waveFreeBlockCount)*period_size;
if(buf < 0)
buf = 0;
return buf;
}
qint64 QAudioInputPrivate::read(char* data, qint64 len)
{
bool done = false;
char* p = data;
qint64 l = 0;
qint64 written = 0;
while(!done) {
// Read in some audio data
if(waveBlocks[header].dwBytesRecorded > 0 && waveBlocks[header].dwFlags & WHDR_DONE) {
if(pullMode) {
l = audioSource->write(waveBlocks[header].lpData + waveBlockOffset,
waveBlocks[header].dwBytesRecorded - waveBlockOffset);
#ifdef DEBUG_AUDIO
qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
#endif
if(l < 0) {
// error
qWarning("QAudioInput: IOError");
errorState = QAudio::IOError;
} else if(l == 0) {
// cant write to IODevice
qWarning("QAudioInput: IOError, can't write to QIODevice");
errorState = QAudio::IOError;
} else {
totalTimeValue += l;
errorState = QAudio::NoError;
if (deviceState != QAudio::ActiveState) {
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
resuming = false;
}
} else {
l = qMin<qint64>(len, waveBlocks[header].dwBytesRecorded - waveBlockOffset);
// push mode
memcpy(p, waveBlocks[header].lpData + waveBlockOffset, l);
len -= l;
#ifdef DEBUG_AUDIO
qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
#endif
totalTimeValue += l;
errorState = QAudio::NoError;
if (deviceState != QAudio::ActiveState) {
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
resuming = false;
}
} else {
//no data, not ready yet, next time
break;
}
if (l < waveBlocks[header].dwBytesRecorded - waveBlockOffset) {
waveBlockOffset += l;
done = true;
} else {
waveBlockOffset = 0;
waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
mutex.lock();
waveFreeBlockCount++;
mutex.unlock();
waveBlocks[header].dwBytesRecorded=0;
waveBlocks[header].dwFlags = 0L;
result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
if(result != MMSYSERR_NOERROR) {
result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result);
errorState = QAudio::IOError;
mutex.lock();
waveFreeBlockCount--;
mutex.unlock();
return 0;
}
result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR));
if(result != MMSYSERR_NOERROR) {
qWarning("QAudioInput: failed to setup block %d,err=%d",header,result);
errorState = QAudio::IOError;
mutex.lock();
waveFreeBlockCount--;
mutex.unlock();
return 0;
}
header++;
if(header >= buffer_size/period_size)
header = 0;
p+=l;
mutex.lock();
if(!pullMode) {
if(len < period_size || waveFreeBlockCount == buffer_size/period_size)
done = true;
} else {
if(waveFreeBlockCount == buffer_size/period_size)
done = true;
}
mutex.unlock();
}
written+=l;
}
#ifdef DEBUG_AUDIO
qDebug()<<"read in len="<<written;
#endif
return written;
}
void QAudioInputPrivate::resume()
{
if(deviceState == QAudio::SuspendedState) {
deviceState = QAudio::ActiveState;
for(int i=0; i<buffer_size/period_size; i++) {
result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR));
if(result != MMSYSERR_NOERROR) {
qWarning("QAudioInput: failed to setup block %d,err=%d",i,result);
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return;
}
}
mutex.lock();
waveFreeBlockCount = buffer_size/period_size;
mutex.unlock();
header = 0;
resuming = true;
waveBlockOffset = 0;
waveInStart(hWaveIn);
QTimer::singleShot(20,this,SLOT(feedback()));
emit stateChanged(deviceState);
}
}
void QAudioInputPrivate::setBufferSize(int value)
{
buffer_size = value;
}
int QAudioInputPrivate::bufferSize() const
{
return buffer_size;
}
int QAudioInputPrivate::periodSize() const
{
return period_size;
}
void QAudioInputPrivate::setNotifyInterval(int ms)
{
intervalTime = qMax(0, ms);
}
int QAudioInputPrivate::notifyInterval() const
{
return intervalTime;
}
qint64 QAudioInputPrivate::processedUSecs() const
{
if (deviceState == QAudio::StoppedState)
return 0;
qint64 result = qint64(1000000) * totalTimeValue /
(settings.channels()*(settings.sampleSize()/8)) /
settings.frequency();
return result;
}
void QAudioInputPrivate::suspend()
{
if(deviceState == QAudio::ActiveState) {
waveInReset(hWaveIn);
deviceState = QAudio::SuspendedState;
emit stateChanged(deviceState);
}
}
void QAudioInputPrivate::feedback()
{
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this;
#endif
if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState))
QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection);
}
bool QAudioInputPrivate::deviceReady()
{
bytesAvailable = bytesReady();
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT";
#endif
if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return true;
if(pullMode) {
// reads some audio data and writes it to QIODevice
read(0, buffer_size);
} else {
// emits readyRead() so user will call read() on QIODevice to get some audio data
InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
a->trigger();
}
if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
emit notify();
elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
timeStamp.restart();
}
return true;
}
qint64 QAudioInputPrivate::elapsedUSecs() const
{
if (deviceState == QAudio::StoppedState)
return 0;
return timeStampOpened.elapsed()*1000;
}
void QAudioInputPrivate::reset()
{
stop();
if (period_size > 0)
waveFreeBlockCount = buffer_size / period_size;
}
InputPrivate::InputPrivate(QAudioInputPrivate* audio)
{
audioDevice = qobject_cast<QAudioInputPrivate*>(audio);
}
InputPrivate::~InputPrivate() {}
qint64 InputPrivate::readData( char* data, qint64 len)
{
// push mode, user read() called
if(audioDevice->deviceState != QAudio::ActiveState &&
audioDevice->deviceState != QAudio::IdleState)
return 0;
// Read in some audio data
return audioDevice->read(data,len);
}
qint64 InputPrivate::writeData(const char* data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)
emit readyRead();
return 0;
}
void InputPrivate::trigger()
{
emit readyRead();
}
QT_END_NAMESPACE
#include "moc_qaudioinput_win32_p.cpp"

View File

@@ -0,0 +1,179 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUTWIN_H
#define QAUDIOINPUTWIN_H
#include <windows.h>
#include <mmsystem.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmutex.h>
#include <qaudio.h>
#include <qaudiodeviceinfo.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
// For compat with 4.6
#if !defined(QT_WIN_CALLBACK)
# if defined(Q_CC_MINGW)
# define QT_WIN_CALLBACK CALLBACK __attribute__ ((force_align_arg_pointer))
# else
# define QT_WIN_CALLBACK CALLBACK
# endif
#endif
class QAudioInputPrivate : public QAbstractAudioInput
{
Q_OBJECT
public:
QAudioInputPrivate(const QByteArray &device);
~QAudioInputPrivate();
qint64 read(char* data, qint64 len);
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private:
qint32 buffer_size;
qint32 period_size;
qint32 header;
QByteArray m_device;
int bytesAvailable;
int intervalTime;
QTime timeStamp;
qint64 elapsedTimeOffset;
QTime timeStampOpened;
qint64 totalTimeValue;
bool pullMode;
bool resuming;
WAVEFORMATEX wfx;
HWAVEIN hWaveIn;
MMRESULT result;
WAVEHDR* waveBlocks;
volatile bool finished;
volatile int waveFreeBlockCount;
int waveBlockOffset;
QMutex mutex;
static void QT_WIN_CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
WAVEHDR* allocateBlocks(int size, int count);
void freeBlocks(WAVEHDR* blockArray);
bool open();
void close();
private slots:
void feedback();
bool deviceReady();
signals:
void processMore();
};
class InputPrivate : public QIODevice
{
Q_OBJECT
public:
InputPrivate(QAudioInputPrivate* audio);
~InputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
void trigger();
private:
QAudioInputPrivate *audioDevice;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,404 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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
\since 1.0
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.
\since 1.0
*/
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.
\since 1.0
*/
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.
\since 1.0
*/
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.
\since 1.0
\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.
\since 1.0
\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.
\since 1.0
*/
void QAudioOutput::stop()
{
d->stop();
}
/*!
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
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.
\since 1.0
*/
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.
\since 1.0
*/
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.
\since 1.0
*/
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.
\since 1.0
*/
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.
\since 1.0
*/
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().
\since 1.0
*/
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.
\since 1.0
*/
void QAudioOutput::setNotifyInterval(int ms)
{
d->setNotifyInterval(ms);
}
/*!
Returns the notify interval in milliseconds.
\since 1.0
*/
int QAudioOutput::notifyInterval() const
{
return d->notifyInterval();
}
/*!
Returns the amount of audio data processed since start()
was called (in microseconds).
\since 1.0
*/
qint64 QAudioOutput::processedUSecs() const
{
return d->processedUSecs();
}
/*!
Returns the microseconds since start() was called, including time in Idle and
Suspend states.
\since 1.0
*/
qint64 QAudioOutput::elapsedUSecs() const
{
return d->elapsedUSecs();
}
/*!
Returns the error state.
\since 1.0
*/
QAudio::Error QAudioOutput::error() const
{
return d->error();
}
/*!
Returns the state of audio processing.
\since 1.0
*/
QAudio::State QAudioOutput::state() const
{
return d->state();
}
/*!
Sets the volume.
Where \a volume is between 0.0 and 1.0 inclusive.
\since 5.0
*/
void QAudioOutput::setVolume(qreal volume)
{
d->setVolume(volume);
}
/*!
Returns the volume between 0.0 and 1.0 inclusive.
\since 5.0
*/
qreal QAudioOutput::volume() const
{
return d->volume();
}
/*!
\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.
\since 1.0
*/
/*!
\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().
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudiooutput.cpp"

View File

@@ -0,0 +1,117 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOOUTPUT_H
#define QAUDIOOUTPUT_H
#include <QtCore/qiodevice.h>
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiodeviceinfo.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAbstractAudioOutput;
class Q_MULTIMEDIA_EXPORT QAudioOutput : public QObject
{
Q_OBJECT
public:
explicit QAudioOutput(const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
explicit QAudioOutput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
~QAudioOutput();
QAudioFormat format() const;
void start(QIODevice *device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
void setBufferSize(int bytes);
int bufferSize() const;
int bytesFree() const;
int periodSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void setVolume(qreal);
qreal volume() const;
Q_SIGNALS:
void stateChanged(QAudio::State);
void notify();
private:
Q_DISABLE_COPY(QAudioOutput)
QAbstractAudioOutput* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOOUTPUT_H

View File

@@ -0,0 +1,834 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <QtCore/qcoreapplication.h>
#include "qaudiooutput_alsa_p.h"
#include "qaudiodeviceinfo_alsa_p.h"
QT_BEGIN_NAMESPACE
//#define DEBUG_AUDIO 1
QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device)
{
bytesAvailable = 0;
handle = 0;
ahandler = 0;
access = SND_PCM_ACCESS_RW_INTERLEAVED;
pcmformat = SND_PCM_FORMAT_S16;
buffer_frames = 0;
period_frames = 0;
buffer_size = 0;
period_size = 0;
buffer_time = 100000;
period_time = 20000;
totalTimeValue = 0;
intervalTime = 1000;
audioBuffer = 0;
errorState = QAudio::NoError;
deviceState = QAudio::StoppedState;
audioSource = 0;
pullMode = true;
resuming = false;
opened = false;
m_device = device;
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),SLOT(userFeed()));
}
QAudioOutputPrivate::~QAudioOutputPrivate()
{
close();
disconnect(timer, SIGNAL(timeout()));
QCoreApplication::processEvents();
delete timer;
}
QAudio::Error QAudioOutputPrivate::error() const
{
return errorState;
}
QAudio::State QAudioOutputPrivate::state() const
{
return deviceState;
}
void QAudioOutputPrivate::async_callback(snd_async_handler_t *ahandler)
{
QAudioOutputPrivate* audioOut;
audioOut = static_cast<QAudioOutputPrivate*>
(snd_async_handler_get_callback_private(ahandler));
if((audioOut->deviceState==QAudio::ActiveState)||(audioOut->resuming))
audioOut->feedback();
}
int QAudioOutputPrivate::xrun_recovery(int err)
{
int count = 0;
bool reset = false;
if(err == -EPIPE) {
errorState = QAudio::UnderrunError;
emit errorChanged(errorState);
err = snd_pcm_prepare(handle);
if(err < 0)
reset = true;
} else if((err == -ESTRPIPE)||(err == -EIO)) {
errorState = QAudio::IOError;
emit errorChanged(errorState);
while((err = snd_pcm_resume(handle)) == -EAGAIN){
usleep(100);
count++;
if(count > 5) {
reset = true;
break;
}
}
if(err < 0) {
err = snd_pcm_prepare(handle);
if(err < 0)
reset = true;
}
}
if(reset) {
close();
open();
snd_pcm_prepare(handle);
return 0;
}
return err;
}
int QAudioOutputPrivate::setFormat()
{
snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN;
if(settings.sampleSize() == 8) {
pcmformat = SND_PCM_FORMAT_U8;
} else if(settings.sampleSize() == 16) {
if(settings.sampleType() == QAudioFormat::SignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_S16_LE;
else
pcmformat = SND_PCM_FORMAT_S16_BE;
} else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_U16_LE;
else
pcmformat = SND_PCM_FORMAT_U16_BE;
}
} else if(settings.sampleSize() == 24) {
if(settings.sampleType() == QAudioFormat::SignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_S24_LE;
else
pcmformat = SND_PCM_FORMAT_S24_BE;
} else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_U24_LE;
else
pcmformat = SND_PCM_FORMAT_U24_BE;
}
} else if(settings.sampleSize() == 32) {
if(settings.sampleType() == QAudioFormat::SignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_S32_LE;
else
pcmformat = SND_PCM_FORMAT_S32_BE;
} else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_U32_LE;
else
pcmformat = SND_PCM_FORMAT_U32_BE;
} else if(settings.sampleType() == QAudioFormat::Float) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_FLOAT_LE;
else
pcmformat = SND_PCM_FORMAT_FLOAT_BE;
}
} else if(settings.sampleSize() == 64) {
if(settings.byteOrder() == QAudioFormat::LittleEndian)
pcmformat = SND_PCM_FORMAT_FLOAT64_LE;
else
pcmformat = SND_PCM_FORMAT_FLOAT64_BE;
}
return pcmformat != SND_PCM_FORMAT_UNKNOWN
? snd_pcm_hw_params_set_format( handle, hwparams, pcmformat)
: -1;
}
void QAudioOutputPrivate::start(QIODevice* device)
{
if(deviceState != QAudio::StoppedState)
deviceState = QAudio::StoppedState;
errorState = QAudio::NoError;
// Handle change of mode
if(audioSource && !pullMode) {
delete audioSource;
audioSource = 0;
}
close();
pullMode = true;
audioSource = device;
deviceState = QAudio::ActiveState;
open();
emit stateChanged(deviceState);
}
QIODevice* QAudioOutputPrivate::start()
{
if(deviceState != QAudio::StoppedState)
deviceState = QAudio::StoppedState;
errorState = QAudio::NoError;
// Handle change of mode
if(audioSource && !pullMode) {
delete audioSource;
audioSource = 0;
}
close();
audioSource = new OutputPrivate(this);
audioSource->open(QIODevice::WriteOnly|QIODevice::Unbuffered);
pullMode = false;
deviceState = QAudio::IdleState;
open();
emit stateChanged(deviceState);
return audioSource;
}
void QAudioOutputPrivate::stop()
{
if(deviceState == QAudio::StoppedState)
return;
errorState = QAudio::NoError;
deviceState = QAudio::StoppedState;
close();
emit stateChanged(deviceState);
}
bool QAudioOutputPrivate::open()
{
if(opened)
return true;
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
timeStamp.restart();
elapsedTimeOffset = 0;
int dir;
int err = 0;
int count=0;
unsigned int freakuency=settings.frequency();
if (!settings.isValid()) {
qWarning("QAudioOutput: open error, invalid format.");
} else if (settings.sampleRate() <= 0) {
qWarning("QAudioOutput: open error, invalid sample rate (%d).",
settings.sampleRate());
} else {
err = -1;
}
if (err == 0) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit errorChanged(errorState);
return false;
}
QString dev = QString(QLatin1String(m_device.constData()));
QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
if (devices.size() > 0)
dev = QLatin1String(devices.first());
else
return false;
#else
dev = QLatin1String("hw:0,0");
#endif
} else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = QLatin1String(m_device);
#else
int idx = 0;
char *name;
QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData());
while(snd_card_get_name(idx,&name) == 0) {
if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0)
break;
idx++;
}
dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
}
// Step 1: try and open the device
while((count < 5) && (err < 0)) {
err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
if(err < 0)
count++;
}
if (( err < 0)||(handle == 0)) {
errorState = QAudio::OpenError;
emit errorChanged(errorState);
deviceState = QAudio::StoppedState;
return false;
}
snd_pcm_nonblock( handle, 0 );
// Step 2: Set the desired HW parameters.
snd_pcm_hw_params_alloca( &hwparams );
bool fatal = false;
QString errMessage;
unsigned int chunks = 8;
err = snd_pcm_hw_params_any( handle, hwparams );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_any: err = %1").arg(err);
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_access( handle, hwparams, access );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_access: err = %1").arg(err);
}
}
if ( !fatal ) {
err = setFormat();
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_format: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_channels: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 );
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err);
}
}
if ( !fatal ) {
unsigned int maxBufferTime = 0;
unsigned int minBufferTime = 0;
unsigned int maxPeriodTime = 0;
unsigned int minPeriodTime = 0;
err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &dir);
if ( err >= 0)
err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &dir);
if ( err >= 0)
err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &dir);
if ( err >= 0)
err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err);
} else {
if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) {
#ifdef DEBUG_AUDIO
qDebug()<<"defaults out of range";
qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime;
#endif
period_time = minPeriodTime;
if (period_time*4 <= maxBufferTime) {
// Use 4 periods if possible
buffer_time = period_time*4;
chunks = 4;
} else if (period_time*2 <= maxBufferTime) {
// Use 2 periods if possible
buffer_time = period_time*2;
chunks = 2;
} else {
qWarning()<<"QAudioOutput: alsa only supports single period!";
fatal = true;
}
#ifdef DEBUG_AUDIO
qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time;
#endif
}
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err);
}
}
if ( !fatal ) {
err = snd_pcm_hw_params(handle, hwparams);
if ( err < 0 ) {
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params: err = %1").arg(err);
}
}
if( err < 0) {
qWarning()<<errMessage;
errorState = QAudio::OpenError;
emit errorChanged(errorState);
deviceState = QAudio::StoppedState;
return false;
}
snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
period_size = snd_pcm_frames_to_bytes(handle,period_frames);
snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);
// Step 3: Set the desired SW parameters.
snd_pcm_sw_params_t *swparams;
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_sw_params_current(handle, swparams);
snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames);
snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames);
snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames);
snd_pcm_sw_params(handle, swparams);
// Step 4: Prepare audio
if(audioBuffer == 0)
audioBuffer = new char[snd_pcm_frames_to_bytes(handle,buffer_frames)];
snd_pcm_prepare( handle );
snd_pcm_start(handle);
// Step 5: Setup callback and timer fallback
snd_async_add_pcm_handler(&ahandler, handle, async_callback, this);
bytesAvailable = bytesFree();
// Step 6: Start audio processing
timer->start(period_time/1000);
clockStamp.restart();
timeStamp.restart();
elapsedTimeOffset = 0;
errorState = QAudio::NoError;
totalTimeValue = 0;
opened = true;
return true;
}
void QAudioOutputPrivate::close()
{
timer->stop();
if ( handle ) {
snd_pcm_drain( handle );
snd_pcm_close( handle );
handle = 0;
delete [] audioBuffer;
audioBuffer=0;
}
if(!pullMode && audioSource) {
delete audioSource;
audioSource = 0;
}
opened = false;
}
int QAudioOutputPrivate::bytesFree() const
{
if(resuming)
return period_size;
if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return 0;
int frames = snd_pcm_avail_update(handle);
if (frames == -EPIPE) {
// Try and handle buffer underrun
int err = snd_pcm_recover(handle, frames, 0);
if (err < 0)
return 0;
else
frames = snd_pcm_avail_update(handle);
} else if (frames < 0) {
return 0;
}
if ((int)frames > (int)buffer_frames)
frames = buffer_frames;
return snd_pcm_frames_to_bytes(handle, frames);
}
qint64 QAudioOutputPrivate::write( const char *data, qint64 len )
{
// Write out some audio data
if ( !handle )
return 0;
#ifdef DEBUG_AUDIO
qDebug()<<"frames to write out = "<<
snd_pcm_bytes_to_frames( handle, (int)len )<<" ("<<len<<") bytes";
#endif
int frames, err;
int space = bytesFree();
if(len < space) {
// Just write it
frames = snd_pcm_bytes_to_frames( handle, (int)len );
err = snd_pcm_writei( handle, data, frames );
} else {
// Only write space worth
frames = snd_pcm_bytes_to_frames( handle, (int)space );
err = snd_pcm_writei( handle, data, frames );
}
if(err > 0) {
totalTimeValue += err;
resuming = false;
errorState = QAudio::NoError;
if (deviceState != QAudio::ActiveState) {
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
return snd_pcm_frames_to_bytes( handle, err );
} else
err = xrun_recovery(err);
if(err < 0) {
close();
errorState = QAudio::FatalError;
emit errorChanged(errorState);
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
}
return 0;
}
int QAudioOutputPrivate::periodSize() const
{
return period_size;
}
void QAudioOutputPrivate::setBufferSize(int value)
{
if(deviceState == QAudio::StoppedState)
buffer_size = value;
}
int QAudioOutputPrivate::bufferSize() const
{
return buffer_size;
}
void QAudioOutputPrivate::setNotifyInterval(int ms)
{
intervalTime = qMax(0, ms);
}
int QAudioOutputPrivate::notifyInterval() const
{
return intervalTime;
}
qint64 QAudioOutputPrivate::processedUSecs() const
{
return qint64(1000000) * totalTimeValue / settings.frequency();
}
void QAudioOutputPrivate::resume()
{
if(deviceState == QAudio::SuspendedState) {
int err = 0;
if(handle) {
err = snd_pcm_prepare( handle );
if(err < 0)
xrun_recovery(err);
err = snd_pcm_start(handle);
if(err < 0)
xrun_recovery(err);
bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames);
}
resuming = true;
deviceState = QAudio::ActiveState;
errorState = QAudio::NoError;
timer->start(period_time/1000);
emit stateChanged(deviceState);
}
}
void QAudioOutputPrivate::setFormat(const QAudioFormat& fmt)
{
if (deviceState == QAudio::StoppedState)
settings = fmt;
}
QAudioFormat QAudioOutputPrivate::format() const
{
return settings;
}
void QAudioOutputPrivate::suspend()
{
if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState || resuming) {
timer->stop();
deviceState = QAudio::SuspendedState;
errorState = QAudio::NoError;
emit stateChanged(deviceState);
}
}
void QAudioOutputPrivate::userFeed()
{
if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState)
return;
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :userFeed() OUT";
#endif
if(deviceState == QAudio::IdleState)
bytesAvailable = bytesFree();
deviceReady();
}
void QAudioOutputPrivate::feedback()
{
updateAvailable();
}
void QAudioOutputPrivate::updateAvailable()
{
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :updateAvailable()";
#endif
bytesAvailable = bytesFree();
}
bool QAudioOutputPrivate::deviceReady()
{
if(pullMode) {
int l = 0;
int chunks = bytesAvailable/period_size;
if(chunks==0) {
bytesAvailable = bytesFree();
return false;
}
#ifdef DEBUG_AUDIO
qDebug()<<"deviceReady() avail="<<bytesAvailable<<" bytes, period size="<<period_size<<" bytes";
qDebug()<<"deviceReady() no. of chunks that can fit ="<<chunks<<", chunks in bytes ="<<period_size*chunks;
#endif
int input = period_frames*chunks;
if(input > (int)buffer_frames)
input = buffer_frames;
l = audioSource->read(audioBuffer,snd_pcm_frames_to_bytes(handle, input));
if(l > 0) {
// Got some data to output
if(deviceState != QAudio::ActiveState)
return true;
qint64 bytesWritten = write(audioBuffer,l);
if (bytesWritten != l)
audioSource->seek(audioSource->pos()-(l-bytesWritten));
bytesAvailable = bytesFree();
} else if(l == 0) {
// Did not get any data to output
bytesAvailable = bytesFree();
if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) {
// Underrun
if (deviceState != QAudio::IdleState) {
errorState = QAudio::UnderrunError;
emit errorChanged(errorState);
deviceState = QAudio::IdleState;
emit stateChanged(deviceState);
}
}
} else if(l < 0) {
close();
deviceState = QAudio::StoppedState;
errorState = QAudio::IOError;
emit errorChanged(errorState);
emit stateChanged(deviceState);
}
} else {
bytesAvailable = bytesFree();
if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) {
// Underrun
if (deviceState != QAudio::IdleState) {
errorState = QAudio::UnderrunError;
emit errorChanged(errorState);
deviceState = QAudio::IdleState;
emit stateChanged(deviceState);
}
}
}
if(deviceState != QAudio::ActiveState)
return true;
if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
emit notify();
elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
timeStamp.restart();
}
return true;
}
qint64 QAudioOutputPrivate::elapsedUSecs() const
{
if (deviceState == QAudio::StoppedState)
return 0;
return clockStamp.elapsed()*1000;
}
void QAudioOutputPrivate::reset()
{
if(handle)
snd_pcm_reset(handle);
stop();
}
OutputPrivate::OutputPrivate(QAudioOutputPrivate* audio)
{
audioDevice = qobject_cast<QAudioOutputPrivate*>(audio);
}
OutputPrivate::~OutputPrivate() {}
qint64 OutputPrivate::readData( char* data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)
return 0;
}
qint64 OutputPrivate::writeData(const char* data, qint64 len)
{
int retry = 0;
qint64 written = 0;
if((audioDevice->deviceState == QAudio::ActiveState)
||(audioDevice->deviceState == QAudio::IdleState)) {
while(written < len) {
int chunk = audioDevice->write(data+written,(len-written));
if(chunk <= 0)
retry++;
written+=chunk;
if(retry > 10)
return written;
}
}
return written;
}
QT_END_NAMESPACE
#include "moc_qaudiooutput_alsa_p.cpp"

View File

@@ -0,0 +1,175 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUTALSA_H
#define QAUDIOOUTPUTALSA_H
#include <alsa/asoundlib.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class OutputPrivate;
class QAudioOutputPrivate : public QAbstractAudioOutput
{
friend class OutputPrivate;
Q_OBJECT
public:
QAudioOutputPrivate(const QByteArray &device);
~QAudioOutputPrivate();
qint64 write( const char *data, qint64 len );
void start(QIODevice* device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private slots:
void userFeed();
void feedback();
void updateAvailable();
bool deviceReady();
signals:
void processMore();
private:
bool opened;
bool pullMode;
bool resuming;
int buffer_size;
int period_size;
int intervalTime;
qint64 totalTimeValue;
unsigned int buffer_time;
unsigned int period_time;
snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames;
static void async_callback(snd_async_handler_t *ahandler);
int xrun_recovery(int err);
int setFormat();
bool open();
void close();
QTimer* timer;
QByteArray m_device;
int bytesAvailable;
QTime timeStamp;
QTime clockStamp;
qint64 elapsedTimeOffset;
char* audioBuffer;
snd_pcm_t* handle;
snd_async_handler_t* ahandler;
snd_pcm_access_t access;
snd_pcm_format_t pcmformat;
snd_timestamp_t* timestamp;
snd_pcm_hw_params_t *hwparams;
};
class OutputPrivate : public QIODevice
{
friend class QAudioOutputPrivate;
Q_OBJECT
public:
OutputPrivate(QAudioOutputPrivate* audio);
~OutputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
private:
QAudioOutputPrivate *audioDevice;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,734 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QtCore/qendian.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qtimer.h>
#include <QtCore/qdebug.h>
#include <qaudiooutput.h>
#include "qaudio_mac_p.h"
#include "qaudiooutput_mac_p.h"
#include "qaudiodeviceinfo_mac_p.h"
QT_BEGIN_NAMESPACE
namespace QtMultimediaInternal
{
static const int default_buffer_size = 8 * 1024;
class QAudioOutputBuffer : public QObject
{
Q_OBJECT
public:
QAudioOutputBuffer(int bufferSize, int maxPeriodSize, QAudioFormat const& audioFormat):
m_deviceError(false),
m_maxPeriodSize(maxPeriodSize),
m_device(0)
{
m_buffer = new QAudioRingBuffer(bufferSize + (bufferSize % maxPeriodSize == 0 ? 0 : maxPeriodSize - (bufferSize % maxPeriodSize)));
m_bytesPerFrame = (audioFormat.sampleSize() / 8) * audioFormat.channels();
m_periodTime = m_maxPeriodSize / m_bytesPerFrame * 1000 / audioFormat.frequency();
m_fillTimer = new QTimer(this);
connect(m_fillTimer, SIGNAL(timeout()), SLOT(fillBuffer()));
}
~QAudioOutputBuffer()
{
delete m_buffer;
}
qint64 readFrames(char* data, qint64 maxFrames)
{
bool wecan = true;
qint64 framesRead = 0;
while (wecan && framesRead < maxFrames) {
QAudioRingBuffer::Region region = m_buffer->acquireReadRegion((maxFrames - framesRead) * m_bytesPerFrame);
if (region.second > 0) {
// Ensure that we only read whole frames.
region.second -= region.second % m_bytesPerFrame;
if (region.second > 0) {
memcpy(data + (framesRead * m_bytesPerFrame), region.first, region.second);
framesRead += region.second / m_bytesPerFrame;
} else
wecan = false; // If there is only a partial frame left we should exit.
}
else
wecan = false;
m_buffer->releaseReadRegion(region);
}
if (framesRead == 0 && m_deviceError)
framesRead = -1;
return framesRead;
}
qint64 writeBytes(const char* data, qint64 maxSize)
{
bool wecan = true;
qint64 bytesWritten = 0;
maxSize -= maxSize % m_bytesPerFrame;
while (wecan && bytesWritten < maxSize) {
QAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(maxSize - bytesWritten);
if (region.second > 0) {
memcpy(region.first, data + bytesWritten, region.second);
bytesWritten += region.second;
}
else
wecan = false;
m_buffer->releaseWriteRegion(region);
}
if (bytesWritten > 0)
emit readyRead();
return bytesWritten;
}
int available() const
{
return m_buffer->free();
}
void reset()
{
m_buffer->reset();
m_device = 0;
m_deviceError = false;
}
void setPrefetchDevice(QIODevice* device)
{
if (m_device != device) {
m_device = device;
if (m_device != 0)
fillBuffer();
}
}
void startFillTimer()
{
if (m_device != 0)
m_fillTimer->start(m_buffer->size() / 2 / m_maxPeriodSize * m_periodTime);
}
void stopFillTimer()
{
m_fillTimer->stop();
}
signals:
void readyRead();
private slots:
void fillBuffer()
{
const int free = m_buffer->free();
const int writeSize = free - (free % m_maxPeriodSize);
if (writeSize > 0) {
bool wecan = true;
int filled = 0;
while (!m_deviceError && wecan && filled < writeSize) {
QAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(writeSize - filled);
if (region.second > 0) {
region.second = m_device->read(region.first, region.second);
if (region.second > 0)
filled += region.second;
else if (region.second == 0)
wecan = false;
else if (region.second < 0) {
m_fillTimer->stop();
region.second = 0;
m_deviceError = true;
}
}
else
wecan = false;
m_buffer->releaseWriteRegion(region);
}
if (filled > 0)
emit readyRead();
}
}
private:
bool m_deviceError;
int m_maxPeriodSize;
int m_bytesPerFrame;
int m_periodTime;
QIODevice* m_device;
QTimer* m_fillTimer;
QAudioRingBuffer* m_buffer;
};
}
class MacOutputDevice : public QIODevice
{
Q_OBJECT
public:
MacOutputDevice(QtMultimediaInternal::QAudioOutputBuffer* audioBuffer, QObject* parent):
QIODevice(parent),
m_audioBuffer(audioBuffer)
{
open(QIODevice::WriteOnly | QIODevice::Unbuffered);
}
qint64 readData(char* data, qint64 len)
{
Q_UNUSED(data);
Q_UNUSED(len);
return 0;
}
qint64 writeData(const char* data, qint64 len)
{
return m_audioBuffer->writeBytes(data, len);
}
bool isSequential() const
{
return true;
}
private:
QtMultimediaInternal::QAudioOutputBuffer* m_audioBuffer;
};
QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray& device)
{
QDataStream ds(device);
quint32 did, mode;
ds >> did >> mode;
if (QAudio::Mode(mode) == QAudio::AudioInput)
errorCode = QAudio::OpenError;
else {
audioDeviceInfo = new QAudioDeviceInfoInternal(device, QAudio::AudioOutput);
isOpen = false;
audioDeviceId = AudioDeviceID(did);
audioUnit = 0;
audioIO = 0;
startTime = 0;
totalFrames = 0;
audioBuffer = 0;
internalBufferSize = QtMultimediaInternal::default_buffer_size;
clockFrequency = AudioGetHostClockFrequency() / 1000;
errorCode = QAudio::NoError;
stateCode = QAudio::StoppedState;
audioThreadState = Stopped;
intervalTimer = new QTimer(this);
intervalTimer->setInterval(1000);
connect(intervalTimer, SIGNAL(timeout()), SIGNAL(notify()));
}
}
QAudioOutputPrivate::~QAudioOutputPrivate()
{
delete audioDeviceInfo;
close();
}
bool QAudioOutputPrivate::open()
{
if (errorCode != QAudio::NoError)
return false;
if (isOpen)
return true;
ComponentDescription cd;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_HALOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
// Open
Component cp = FindNextComponent(NULL, &cd);
if (cp == 0) {
qWarning() << "QAudioOutput: Failed to find HAL Output component";
return false;
}
if (OpenAComponent(cp, &audioUnit) != noErr) {
qWarning() << "QAudioOutput: Unable to Open Output Component";
return false;
}
// register callback
AURenderCallbackStruct cb;
cb.inputProc = renderCallback;
cb.inputProcRefCon = this;
if (AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
0,
&cb,
sizeof(cb)) != noErr) {
qWarning() << "QAudioOutput: Failed to set AudioUnit callback";
return false;
}
// Set Audio Device
if (AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&audioDeviceId,
sizeof(audioDeviceId)) != noErr) {
qWarning() << "QAudioOutput: Unable to use configured device";
return false;
}
// Set stream format
streamFormat = toAudioStreamBasicDescription(audioFormat);
UInt32 size = sizeof(streamFormat);
if (AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&streamFormat,
sizeof(streamFormat)) != noErr) {
qWarning() << "QAudioOutput: Unable to Set Stream information";
return false;
}
// Allocate buffer
UInt32 numberOfFrames = 0;
size = sizeof(UInt32);
if (AudioUnitGetProperty(audioUnit,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
0,
&numberOfFrames,
&size) != noErr) {
qWarning() << "QAudioInput: Failed to get audio period size";
return false;
}
periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame;
if (internalBufferSize < periodSizeBytes * 2)
internalBufferSize = periodSizeBytes * 2;
else
internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
audioBuffer = new QtMultimediaInternal::QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat);
connect(audioBuffer, SIGNAL(readyRead()), SLOT(inputReady())); // Pull
audioIO = new MacOutputDevice(audioBuffer, this);
// Init
if (AudioUnitInitialize(audioUnit)) {
qWarning() << "QAudioOutput: Failed to initialize AudioUnit";
return false;
}
isOpen = true;
return true;
}
void QAudioOutputPrivate::close()
{
if (audioUnit != 0) {
AudioOutputUnitStop(audioUnit);
AudioUnitUninitialize(audioUnit);
CloseComponent(audioUnit);
}
delete audioBuffer;
}
QAudioFormat QAudioOutputPrivate::format() const
{
return audioFormat;
}
void QAudioOutputPrivate::setFormat(const QAudioFormat& fmt)
{
if (stateCode == QAudio::StoppedState)
audioFormat = fmt;
}
void QAudioOutputPrivate::start(QIODevice* device)
{
QIODevice* op = device;
if (!audioDeviceInfo->isFormatSupported(audioFormat) || !open()) {
stateCode = QAudio::StoppedState;
errorCode = QAudio::OpenError;
}
reset();
audioBuffer->reset();
audioBuffer->setPrefetchDevice(op);
if (op == 0) {
op = audioIO;
stateCode = QAudio::IdleState;
}
else
stateCode = QAudio::ActiveState;
// Start
errorCode = QAudio::NoError;
totalFrames = 0;
startTime = AudioGetCurrentHostTime();
if (stateCode == QAudio::ActiveState)
audioThreadStart();
emit stateChanged(stateCode);
}
QIODevice* QAudioOutputPrivate::start()
{
if (!audioDeviceInfo->isFormatSupported(audioFormat) || !open()) {
stateCode = QAudio::StoppedState;
errorCode = QAudio::OpenError;
return audioIO;
}
reset();
audioBuffer->reset();
audioBuffer->setPrefetchDevice(0);
stateCode = QAudio::IdleState;
// Start
errorCode = QAudio::NoError;
totalFrames = 0;
startTime = AudioGetCurrentHostTime();
emit stateChanged(stateCode);
return audioIO;
}
void QAudioOutputPrivate::stop()
{
QMutexLocker lock(&mutex);
if (stateCode != QAudio::StoppedState) {
audioThreadDrain();
stateCode = QAudio::StoppedState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioOutputPrivate::reset()
{
QMutexLocker lock(&mutex);
if (stateCode != QAudio::StoppedState) {
audioThreadStop();
stateCode = QAudio::StoppedState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioOutputPrivate::suspend()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState || stateCode == QAudio::IdleState) {
audioThreadStop();
stateCode = QAudio::SuspendedState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioOutputPrivate::resume()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::SuspendedState) {
audioThreadStart();
stateCode = QAudio::ActiveState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
int QAudioOutputPrivate::bytesFree() const
{
return audioBuffer->available();
}
int QAudioOutputPrivate::periodSize() const
{
return periodSizeBytes;
}
void QAudioOutputPrivate::setBufferSize(int bs)
{
if (stateCode == QAudio::StoppedState)
internalBufferSize = bs;
}
int QAudioOutputPrivate::bufferSize() const
{
return internalBufferSize;
}
void QAudioOutputPrivate::setNotifyInterval(int milliSeconds)
{
if (intervalTimer->interval() == milliSeconds)
return;
if (milliSeconds <= 0)
milliSeconds = 0;
intervalTimer->setInterval(milliSeconds);
}
int QAudioOutputPrivate::notifyInterval() const
{
return intervalTimer->interval();
}
qint64 QAudioOutputPrivate::processedUSecs() const
{
return totalFrames * 1000000 / audioFormat.frequency();
}
qint64 QAudioOutputPrivate::elapsedUSecs() const
{
if (stateCode == QAudio::StoppedState)
return 0;
return (AudioGetCurrentHostTime() - startTime) / (clockFrequency / 1000);
}
QAudio::Error QAudioOutputPrivate::error() const
{
return errorCode;
}
QAudio::State QAudioOutputPrivate::state() const
{
return stateCode;
}
void QAudioOutputPrivate::audioThreadStart()
{
startTimers();
audioThreadState = Running;
AudioOutputUnitStart(audioUnit);
}
void QAudioOutputPrivate::audioThreadStop()
{
stopTimers();
if (audioThreadState.testAndSetAcquire(Running, Stopped))
threadFinished.wait(&mutex);
}
void QAudioOutputPrivate::audioThreadDrain()
{
stopTimers();
if (audioThreadState.testAndSetAcquire(Running, Draining))
threadFinished.wait(&mutex);
}
void QAudioOutputPrivate::audioDeviceStop()
{
AudioOutputUnitStop(audioUnit);
audioThreadState = Stopped;
threadFinished.wakeOne();
}
void QAudioOutputPrivate::audioDeviceIdle()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState) {
audioDeviceStop();
errorCode = QAudio::UnderrunError;
stateCode = QAudio::IdleState;
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
}
void QAudioOutputPrivate::audioDeviceError()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState) {
audioDeviceStop();
errorCode = QAudio::IOError;
stateCode = QAudio::StoppedState;
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
}
void QAudioOutputPrivate::startTimers()
{
audioBuffer->startFillTimer();
if (intervalTimer->interval() > 0)
intervalTimer->start();
}
void QAudioOutputPrivate::stopTimers()
{
audioBuffer->stopFillTimer();
intervalTimer->stop();
}
void QAudioOutputPrivate::deviceStopped()
{
intervalTimer->stop();
emit stateChanged(stateCode);
}
void QAudioOutputPrivate::inputReady()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::IdleState) {
audioThreadStart();
stateCode = QAudio::ActiveState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
OSStatus QAudioOutputPrivate::renderCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData)
{
Q_UNUSED(ioActionFlags)
Q_UNUSED(inTimeStamp)
Q_UNUSED(inBusNumber)
Q_UNUSED(inNumberFrames)
QAudioOutputPrivate* d = static_cast<QAudioOutputPrivate*>(inRefCon);
const int threadState = d->audioThreadState.fetchAndAddAcquire(0);
if (threadState == Stopped) {
ioData->mBuffers[0].mDataByteSize = 0;
d->audioDeviceStop();
}
else {
const UInt32 bytesPerFrame = d->streamFormat.mBytesPerFrame;
qint64 framesRead;
framesRead = d->audioBuffer->readFrames((char*)ioData->mBuffers[0].mData,
ioData->mBuffers[0].mDataByteSize / bytesPerFrame);
if (framesRead > 0) {
ioData->mBuffers[0].mDataByteSize = framesRead * bytesPerFrame;
d->totalFrames += framesRead;
}
else {
ioData->mBuffers[0].mDataByteSize = 0;
if (framesRead == 0) {
if (threadState == Draining)
d->audioDeviceStop();
else
d->audioDeviceIdle();
}
else
d->audioDeviceError();
}
}
return noErr;
}
QT_END_NAMESPACE
#include "qaudiooutput_mac_p.moc"

View File

@@ -0,0 +1,174 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUT_MAC_P_H
#define QAUDIOOUTPUT_MAC_P_H
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QtCore/qobject.h>
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QIODevice;
class QAbstractAudioDeviceInfo;
namespace QtMultimediaInternal
{
class QAudioOutputBuffer;
}
class QAudioOutputPrivate : public QAbstractAudioOutput
{
Q_OBJECT
public:
bool isOpen;
int internalBufferSize;
int periodSizeBytes;
qint64 totalFrames;
QAudioFormat audioFormat;
QIODevice* audioIO;
AudioDeviceID audioDeviceId;
AudioUnit audioUnit;
Float64 clockFrequency;
UInt64 startTime;
AudioStreamBasicDescription deviceFormat;
AudioStreamBasicDescription streamFormat;
QtMultimediaInternal::QAudioOutputBuffer* audioBuffer;
QAtomicInt audioThreadState;
QWaitCondition threadFinished;
QMutex mutex;
QTimer* intervalTimer;
QAbstractAudioDeviceInfo *audioDeviceInfo;
QAudio::Error errorCode;
QAudio::State stateCode;
QAudioOutputPrivate(const QByteArray& device);
~QAudioOutputPrivate();
bool open();
void close();
QAudioFormat format() const;
void setFormat(const QAudioFormat& fmt);
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void audioThreadStart();
void audioThreadStop();
void audioThreadDrain();
void audioDeviceStop();
void audioDeviceIdle();
void audioDeviceError();
void startTimers();
void stopTimers();
private slots:
void deviceStopped();
void inputReady();
private:
enum { Running, Draining, Stopped };
static OSStatus renderCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,715 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qaudiooutput_win32_p.h"
#ifndef SPEAKER_FRONT_LEFT
#define SPEAKER_FRONT_LEFT 0x00000001
#define SPEAKER_FRONT_RIGHT 0x00000002
#define SPEAKER_FRONT_CENTER 0x00000004
#define SPEAKER_LOW_FREQUENCY 0x00000008
#define SPEAKER_BACK_LEFT 0x00000010
#define SPEAKER_BACK_RIGHT 0x00000020
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
#define SPEAKER_BACK_CENTER 0x00000100
#define SPEAKER_SIDE_LEFT 0x00000200
#define SPEAKER_SIDE_RIGHT 0x00000400
#define SPEAKER_TOP_CENTER 0x00000800
#define SPEAKER_TOP_FRONT_LEFT 0x00001000
#define SPEAKER_TOP_FRONT_CENTER 0x00002000
#define SPEAKER_TOP_FRONT_RIGHT 0x00004000
#define SPEAKER_TOP_BACK_LEFT 0x00008000
#define SPEAKER_TOP_BACK_CENTER 0x00010000
#define SPEAKER_TOP_BACK_RIGHT 0x00020000
#define SPEAKER_RESERVED 0x7FFC0000
#define SPEAKER_ALL 0x80000000
#endif
#ifndef _WAVEFORMATEXTENSIBLE_
#define _WAVEFORMATEXTENSIBLE_
typedef struct
{
WAVEFORMATEX Format; // Base WAVEFORMATEX data
union
{
WORD wValidBitsPerSample; // Valid bits in each sample container
WORD wSamplesPerBlock; // Samples per block of audio data; valid
// if wBitsPerSample=0 (but rarely used).
WORD wReserved; // Zero if neither case above applies.
} Samples;
DWORD dwChannelMask; // Positions of the audio channels
GUID SubFormat; // Format identifier GUID
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE;
typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE;
#endif
#if !defined(WAVE_FORMAT_EXTENSIBLE)
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#endif
//#define DEBUG_AUDIO 1
QT_BEGIN_NAMESPACE
QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device)
{
bytesAvailable = 0;
buffer_size = 0;
period_size = 0;
m_device = device;
totalTimeValue = 0;
intervalTime = 1000;
audioBuffer = 0;
errorState = QAudio::NoError;
deviceState = QAudio::StoppedState;
audioSource = 0;
pullMode = true;
finished = false;
}
QAudioOutputPrivate::~QAudioOutputPrivate()
{
mutex.lock();
finished = true;
mutex.unlock();
close();
}
void CALLBACK QAudioOutputPrivate::waveOutProc( HWAVEOUT hWaveOut, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
Q_UNUSED(dwParam1)
Q_UNUSED(dwParam2)
Q_UNUSED(hWaveOut)
QAudioOutputPrivate* qAudio;
qAudio = (QAudioOutputPrivate*)(dwInstance);
if(!qAudio)
return;
QMutexLocker(&qAudio->mutex);
switch(uMsg) {
case WOM_OPEN:
qAudio->feedback();
break;
case WOM_CLOSE:
return;
case WOM_DONE:
if(qAudio->finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) {
return;
}
qAudio->waveFreeBlockCount++;
if(qAudio->waveFreeBlockCount >= qAudio->buffer_size/qAudio->period_size)
qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size;
qAudio->feedback();
break;
default:
return;
}
}
WAVEHDR* QAudioOutputPrivate::allocateBlocks(int size, int count)
{
int i;
unsigned char* buffer;
WAVEHDR* blocks;
DWORD totalBufferSize = (size + sizeof(WAVEHDR))*count;
if((buffer=(unsigned char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
totalBufferSize)) == 0) {
qWarning("QAudioOutput: Memory allocation error");
return 0;
}
blocks = (WAVEHDR*)buffer;
buffer += sizeof(WAVEHDR)*count;
for(i = 0; i < count; i++) {
blocks[i].dwBufferLength = size;
blocks[i].lpData = (LPSTR)buffer;
buffer += size;
}
return blocks;
}
void QAudioOutputPrivate::freeBlocks(WAVEHDR* blockArray)
{
WAVEHDR* blocks = blockArray;
int count = buffer_size/period_size;
for(int i = 0; i < count; i++) {
waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR));
blocks++;
}
HeapFree(GetProcessHeap(), 0, blockArray);
}
QAudioFormat QAudioOutputPrivate::format() const
{
return settings;
}
void QAudioOutputPrivate::setFormat(const QAudioFormat& fmt)
{
if (deviceState == QAudio::StoppedState)
settings = fmt;
}
void QAudioOutputPrivate::start(QIODevice* device)
{
if(deviceState != QAudio::StoppedState)
close();
if(!pullMode && audioSource)
delete audioSource;
pullMode = true;
audioSource = device;
deviceState = QAudio::ActiveState;
if(!open())
return;
emit stateChanged(deviceState);
}
QIODevice* QAudioOutputPrivate::start()
{
if(deviceState != QAudio::StoppedState)
close();
if(!pullMode && audioSource)
delete audioSource;
pullMode = false;
audioSource = new OutputPrivate(this);
audioSource->open(QIODevice::WriteOnly|QIODevice::Unbuffered);
deviceState = QAudio::IdleState;
if(!open())
return 0;
emit stateChanged(deviceState);
return audioSource;
}
void QAudioOutputPrivate::stop()
{
if(deviceState == QAudio::StoppedState)
return;
close();
if(!pullMode && audioSource) {
delete audioSource;
audioSource = 0;
}
emit stateChanged(deviceState);
}
bool QAudioOutputPrivate::open()
{
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
period_size = 0;
if (!settings.isValid()) {
qWarning("QAudioOutput: open error, invalid format.");
} else if (settings.channelCount() <= 0) {
qWarning("QAudioOutput: open error, invalid number of channels (%d).",
settings.channelCount());
} else if (settings.sampleSize() <= 0) {
qWarning("QAudioOutput: open error, invalid sample size (%d).",
settings.sampleSize());
} else if (settings.frequency() < 8000 || settings.frequency() > 96000) {
qWarning("QAudioOutput: open error, frequency out of range (%d).", settings.frequency());
} else if (buffer_size == 0) {
// Default buffer size, 200ms, default period size is 40ms
buffer_size
= (settings.frequency()
* settings.channelCount()
* settings.sampleSize()
+ 39) / 40;
period_size = buffer_size / 5;
} else {
period_size = buffer_size / 5;
}
if (period_size == 0) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
return false;
}
waveBlocks = allocateBlocks(period_size, buffer_size/period_size);
mutex.lock();
waveFreeBlockCount = buffer_size/period_size;
mutex.unlock();
waveCurrentBlock = 0;
if(audioBuffer == 0)
audioBuffer = new char[buffer_size];
timeStamp.restart();
elapsedTimeOffset = 0;
wfx.nSamplesPerSec = settings.frequency();
wfx.wBitsPerSample = settings.sampleSize();
wfx.nChannels = settings.channels();
wfx.cbSize = 0;
bool surround = false;
if (settings.channels() > 2)
surround = true;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
QDataStream ds(&m_device, QIODevice::ReadOnly);
quint32 deviceId;
ds >> deviceId;
if (!surround) {
if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx,
(DWORD_PTR)&waveOutProc,
(DWORD_PTR) this,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
qWarning("QAudioOutput: open error");
return false;
}
} else {
WAVEFORMATEXTENSIBLE wfex;
wfex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfex.Format.nChannels = settings.channels();
wfex.Format.wBitsPerSample = settings.sampleSize();
wfex.Format.nSamplesPerSec = settings.frequency();
wfex.Format.nBlockAlign = wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*wfex.Format.nBlockAlign;
wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
wfex.SubFormat=_KSDATAFORMAT_SUBTYPE_PCM;
wfex.Format.cbSize=22;
wfex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
if (settings.channels() >= 4)
wfex.dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
if (settings.channels() >= 6)
wfex.dwChannelMask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY;
if (settings.channels() == 8)
wfex.dwChannelMask |= SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfex.Format,
(DWORD_PTR)&waveOutProc,
(DWORD_PTR) this,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
errorState = QAudio::OpenError;
deviceState = QAudio::StoppedState;
emit stateChanged(deviceState);
qWarning("QAudioOutput: open error");
return false;
}
}
totalTimeValue = 0;
timeStampOpened.restart();
elapsedTimeOffset = 0;
errorState = QAudio::NoError;
if(pullMode) {
deviceState = QAudio::ActiveState;
QTimer::singleShot(10, this, SLOT(feedback()));
} else
deviceState = QAudio::IdleState;
return true;
}
void QAudioOutputPrivate::close()
{
if(deviceState == QAudio::StoppedState)
return;
deviceState = QAudio::StoppedState;
errorState = QAudio::NoError;
int delay = (buffer_size-bytesFree())*1000/(settings.frequency()
*settings.channels()*(settings.sampleSize()/8));
waveOutReset(hWaveOut);
Sleep(delay+10);
freeBlocks(waveBlocks);
waveOutClose(hWaveOut);
delete [] audioBuffer;
audioBuffer = 0;
buffer_size = 0;
}
int QAudioOutputPrivate::bytesFree() const
{
int buf;
buf = waveFreeBlockCount*period_size;
return buf;
}
int QAudioOutputPrivate::periodSize() const
{
return period_size;
}
void QAudioOutputPrivate::setBufferSize(int value)
{
if(deviceState == QAudio::StoppedState)
buffer_size = value;
}
int QAudioOutputPrivate::bufferSize() const
{
return buffer_size;
}
void QAudioOutputPrivate::setNotifyInterval(int ms)
{
intervalTime = qMax(0, ms);
}
int QAudioOutputPrivate::notifyInterval() const
{
return intervalTime;
}
qint64 QAudioOutputPrivate::processedUSecs() const
{
if (deviceState == QAudio::StoppedState)
return 0;
qint64 result = qint64(1000000) * totalTimeValue /
(settings.channels()*(settings.sampleSize()/8)) /
settings.frequency();
return result;
}
qint64 QAudioOutputPrivate::write( const char *data, qint64 len )
{
// Write out some audio data
if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return 0;
char* p = (char*)data;
int l = (int)len;
WAVEHDR* current;
int remain;
current = &waveBlocks[waveCurrentBlock];
while(l > 0) {
mutex.lock();
if(waveFreeBlockCount==0) {
mutex.unlock();
break;
}
mutex.unlock();
if(current->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));
if(l < period_size)
remain = l;
else
remain = period_size;
memcpy(current->lpData, p, remain);
l -= remain;
p += remain;
current->dwBufferLength = remain;
waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
mutex.lock();
waveFreeBlockCount--;
#ifdef DEBUG_AUDIO
qDebug("write out l=%d, waveFreeBlockCount=%d",
current->dwBufferLength,waveFreeBlockCount);
#endif
mutex.unlock();
totalTimeValue += current->dwBufferLength;
waveCurrentBlock++;
waveCurrentBlock %= buffer_size/period_size;
current = &waveBlocks[waveCurrentBlock];
current->dwUser = 0;
errorState = QAudio::NoError;
if (deviceState != QAudio::ActiveState) {
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
}
return (len-l);
}
void QAudioOutputPrivate::resume()
{
if(deviceState == QAudio::SuspendedState) {
deviceState = QAudio::ActiveState;
errorState = QAudio::NoError;
waveOutRestart(hWaveOut);
QTimer::singleShot(10, this, SLOT(feedback()));
emit stateChanged(deviceState);
}
}
void QAudioOutputPrivate::suspend()
{
if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) {
int delay = (buffer_size-bytesFree())*1000/(settings.frequency()
*settings.channels()*(settings.sampleSize()/8));
waveOutPause(hWaveOut);
Sleep(delay+10);
deviceState = QAudio::SuspendedState;
errorState = QAudio::NoError;
emit stateChanged(deviceState);
}
}
void QAudioOutputPrivate::feedback()
{
#ifdef DEBUG_AUDIO
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback()";
#endif
bytesAvailable = bytesFree();
if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState)) {
if(bytesAvailable >= period_size)
QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection);
}
}
bool QAudioOutputPrivate::deviceReady()
{
if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState)
return false;
if(pullMode) {
int chunks = bytesAvailable/period_size;
#ifdef DEBUG_AUDIO
qDebug()<<"deviceReady() avail="<<bytesAvailable<<" bytes, period size="<<period_size<<" bytes";
qDebug()<<"deviceReady() no. of chunks that can fit ="<<chunks<<", chunks in bytes ="<<chunks*period_size;
#endif
bool startup = false;
if(totalTimeValue == 0)
startup = true;
bool full=false;
mutex.lock();
if(waveFreeBlockCount==0) full = true;
mutex.unlock();
if (full){
#ifdef DEBUG_AUDIO
qDebug() << "Skipping data as unable to write";
#endif
if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) {
emit notify();
elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
timeStamp.restart();
}
return true;
}
if(startup)
waveOutPause(hWaveOut);
int input = period_size*chunks;
int l = audioSource->read(audioBuffer,input);
if(l > 0) {
int out= write(audioBuffer,l);
if(out > 0) {
if (deviceState != QAudio::ActiveState) {
deviceState = QAudio::ActiveState;
emit stateChanged(deviceState);
}
}
if ( out < l) {
// Didn't write all data
audioSource->seek(audioSource->pos()-(l-out));
}
if(startup)
waveOutRestart(hWaveOut);
} else if(l == 0) {
bytesAvailable = bytesFree();
int check = 0;
mutex.lock();
check = waveFreeBlockCount;
mutex.unlock();
if(check == buffer_size/period_size) {
if (deviceState != QAudio::IdleState) {
errorState = QAudio::UnderrunError;
deviceState = QAudio::IdleState;
emit stateChanged(deviceState);
}
}
} else if(l < 0) {
bytesAvailable = bytesFree();
if (errorState != QAudio::IOError)
errorState = QAudio::IOError;
}
} else {
int buffered;
mutex.lock();
buffered = waveFreeBlockCount;
mutex.unlock();
if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) {
if (deviceState != QAudio::IdleState) {
errorState = QAudio::UnderrunError;
deviceState = QAudio::IdleState;
emit stateChanged(deviceState);
}
}
}
if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return true;
if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
emit notify();
elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
timeStamp.restart();
}
return true;
}
qint64 QAudioOutputPrivate::elapsedUSecs() const
{
if (deviceState == QAudio::StoppedState)
return 0;
return timeStampOpened.elapsed()*1000;
}
QAudio::Error QAudioOutputPrivate::error() const
{
return errorState;
}
QAudio::State QAudioOutputPrivate::state() const
{
return deviceState;
}
void QAudioOutputPrivate::reset()
{
close();
}
OutputPrivate::OutputPrivate(QAudioOutputPrivate* audio)
{
audioDevice = qobject_cast<QAudioOutputPrivate*>(audio);
}
OutputPrivate::~OutputPrivate() {}
qint64 OutputPrivate::readData( char* data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)
return 0;
}
qint64 OutputPrivate::writeData(const char* data, qint64 len)
{
int retry = 0;
qint64 written = 0;
if((audioDevice->deviceState == QAudio::ActiveState)
||(audioDevice->deviceState == QAudio::IdleState)) {
qint64 l = len;
while(written < l) {
int chunk = audioDevice->write(data+written,(l-written));
if(chunk <= 0)
retry++;
else
written+=chunk;
if(retry > 10)
return written;
}
audioDevice->deviceState = QAudio::ActiveState;
}
return written;
}
QT_END_NAMESPACE
#include "moc_qaudiooutput_win32_p.cpp"

View File

@@ -0,0 +1,175 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUTWIN_H
#define QAUDIOOUTPUTWIN_H
#include <windows.h>
#include <mmsystem.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmutex.h>
#include <qaudio.h>
#include <qaudiodeviceinfo.h>
#include <qaudiosystem.h>
// For compat with 4.6
#if !defined(QT_WIN_CALLBACK)
# if defined(Q_CC_MINGW)
# define QT_WIN_CALLBACK CALLBACK __attribute__ ((force_align_arg_pointer))
# else
# define QT_WIN_CALLBACK CALLBACK
# endif
#endif
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAudioOutputPrivate : public QAbstractAudioOutput
{
Q_OBJECT
public:
QAudioOutputPrivate(const QByteArray &device);
~QAudioOutputPrivate();
qint64 write( const char *data, qint64 len );
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private slots:
void feedback();
bool deviceReady();
private:
QByteArray m_device;
bool resuming;
int bytesAvailable;
QTime timeStamp;
qint64 elapsedTimeOffset;
QTime timeStampOpened;
qint32 buffer_size;
qint32 period_size;
qint64 totalTimeValue;
bool pullMode;
int intervalTime;
static void QT_WIN_CALLBACK waveOutProc( HWAVEOUT hWaveOut, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
QMutex mutex;
WAVEHDR* allocateBlocks(int size, int count);
void freeBlocks(WAVEHDR* blockArray);
bool open();
void close();
WAVEFORMATEX wfx;
HWAVEOUT hWaveOut;
MMRESULT result;
WAVEHDR header;
WAVEHDR* waveBlocks;
volatile bool finished;
volatile int waveFreeBlockCount;
int waveCurrentBlock;
char* audioBuffer;
};
class OutputPrivate : public QIODevice
{
Q_OBJECT
public:
OutputPrivate(QAudioOutputPrivate* audio);
~OutputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
private:
QAudioOutputPrivate *audioDevice;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,176 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudiosystemplugin.h"
#include "qaudiopluginloader_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
QAudioPluginLoader::QAudioPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity):
m_iid(iid)
{
m_location = location + QLatin1Char('/');
load();
}
QAudioPluginLoader::~QAudioPluginLoader()
{
for (int i = 0; i < m_plugins.count(); i++ ) {
delete m_plugins.at(i);
}
}
QStringList QAudioPluginLoader::pluginList() const
{
#if !defined QT_NO_DEBUG
const bool showDebug = qgetenv("QT_DEBUG_PLUGINS").toInt() > 0;
#endif
QStringList paths = QCoreApplication::libraryPaths();
#ifdef QTM_PLUGIN_PATH
paths << QLatin1String(QTM_PLUGIN_PATH);
#endif
#if !defined QT_NO_DEBUG
if (showDebug)
qDebug() << "Plugin paths:" << paths;
#endif
//temp variable to avoid multiple identic path
QSet<QString> processed;
/* Discover a bunch o plugins */
QStringList plugins;
/* Enumerate our plugin paths */
for (int i=0; i < paths.count(); i++) {
if (processed.contains(paths.at(i)))
continue;
processed.insert(paths.at(i));
QDir pluginsDir(paths.at(i)+m_location);
if (!pluginsDir.exists())
continue;
QStringList files = pluginsDir.entryList(QDir::Files);
#if !defined QT_NO_DEBUG
if (showDebug)
qDebug()<<"Looking for plugins in "<<pluginsDir.path()<<files;
#endif
for (int j=0; j < files.count(); j++) {
const QString &file = files.at(j);
plugins << pluginsDir.absoluteFilePath(file);
}
}
return plugins;
}
QStringList QAudioPluginLoader::keys() const
{
QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
QStringList list;
for (int i = 0; i < m_plugins.count(); i++) {
QAudioSystemPlugin* p = qobject_cast<QAudioSystemPlugin*>(m_plugins.at(i)->instance());
if (p) list << p->keys();
}
return list;
}
QObject* QAudioPluginLoader::instance(QString const &key)
{
QMutexLocker locker(&m_mutex);
for (int i = 0; i < m_plugins.count(); i++) {
QAudioSystemPlugin* p = qobject_cast<QAudioSystemPlugin*>(m_plugins.at(i)->instance());
if (p && p->keys().contains(key))
return m_plugins.at(i)->instance();
}
return 0;
}
QList<QObject*> QAudioPluginLoader::instances(QString const &key)
{
QMutexLocker locker(&m_mutex);
QList<QObject*> list;
for (int i = 0; i < m_plugins.count(); i++) {
QAudioSystemPlugin* p = qobject_cast<QAudioSystemPlugin*>(m_plugins.at(i)->instance());
if (p && p->keys().contains(key))
list << m_plugins.at(i)->instance();
}
return list;
}
void QAudioPluginLoader::load()
{
if (!m_plugins.isEmpty())
return;
#if !defined QT_NO_DEBUG
const bool showDebug = qgetenv("QT_DEBUG_PLUGINS").toInt() > 0;
#endif
QStringList plugins = pluginList();
for (int i=0; i < plugins.count(); i++) {
QPluginLoader* loader = new QPluginLoader(plugins.at(i));
QObject *o = loader->instance();
if (o != 0 && o->qt_metacast(m_iid) != 0) {
m_plugins.append(loader);
} else {
#if !defined QT_NO_DEBUG
if (showDebug)
qWarning() << "QAudioPluginLoader: Failed to load plugin: "
<< plugins.at(i) << loader->errorString();
#endif
delete o;
//we are not calling loader->unload here for it may cause problem on some device
delete loader;
}
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,100 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOPLUGINLOADER_H
#define QAUDIOPLUGINLOADER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <qtmultimediadefs.h>
#include <QObject>
#include <QtCore/qstring.h>
#include <QtCore/qmap.h>
#include <QtCore/qmutex.h>
#include <QtCore/qpluginloader.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAudioPluginLoader
{
public:
QAudioPluginLoader(const char *iid,
const QString &suffix = QString(),
Qt::CaseSensitivity = Qt::CaseSensitive);
~QAudioPluginLoader();
QStringList keys() const;
QObject* instance(QString const &key);
QList<QObject*> instances(QString const &key);
private:
QStringList pluginList() const;
void load();
QMutex m_mutex;
QByteArray m_iid;
QString m_location;
QList<QPluginLoader*> m_plugins;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOPLUGINLOADER_H

View File

@@ -0,0 +1,436 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudiosystem.h"
QT_BEGIN_NAMESPACE
/*!
\class QAbstractAudioDeviceInfo
\brief The QAbstractAudioDeviceInfo class is a base class for audio backends.
\ingroup multimedia
\inmodule QtMultimedia
\internal
\since 1.0
This class implements the audio functionality for
QAudioDeviceInfo, i.e., QAudioDeviceInfo keeps a
QAbstractAudioDeviceInfo and routes function calls to it. For a
description of the functionality that QAbstractAudioDeviceInfo
implements, you can read the class and functions documentation of
QAudioDeviceInfo.
\sa QAudioDeviceInfo
\sa QAbstractAudioOutput, QAbstractAudioInput
*/
/*!
\fn virtual QAudioFormat QAbstractAudioDeviceInfo::preferredFormat() const
Returns the recommended settings to use.
\since 1.0
*/
/*!
\fn virtual bool QAbstractAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
Returns true if \a format is available from audio device.
\since 1.0
*/
/*!
\fn virtual QString QAbstractAudioDeviceInfo::deviceName() const
Returns the audio device name.
\since 1.0
*/
/*!
\fn virtual QStringList QAbstractAudioDeviceInfo::supportedCodecs()
Returns the list of currently available codecs.
\since 1.0
*/
/*!
\fn virtual QList<int> QAbstractAudioDeviceInfo::supportedSampleRates()
Returns the list of currently available sample rates.
\since 1.0
*/
/*!
\fn virtual QList<int> QAbstractAudioDeviceInfo::supportedChannelCounts()
Returns the list of currently available channels.
\since 1.0
*/
/*!
\fn virtual QList<int> QAbstractAudioDeviceInfo::supportedSampleSizes()
Returns the list of currently available sample sizes.
\since 1.0
*/
/*!
\fn virtual QList<QAudioFormat::Endian> QAbstractAudioDeviceInfo::supportedByteOrders()
Returns the list of currently available byte orders.
\since 1.0
*/
/*!
\fn virtual QList<QAudioFormat::SampleType> QAbstractAudioDeviceInfo::supportedSampleTypes()
Returns the list of currently available sample types.
\since 1.0
*/
/*!
\class QAbstractAudioOutput
\brief The QAbstractAudioOutput class is a base class for audio backends.
\since 1.0
\ingroup multimedia
\inmodule QtMultimedia
\internal
QAbstractAudioOutput implements audio functionality for
QAudioOutput, i.e., QAudioOutput routes function calls to
QAbstractAudioOutput. For a description of the functionality that
is implemented, see the QAudioOutput class and function
descriptions.
\sa QAudioOutput
*/
/*!
\fn virtual void QAbstractAudioOutput::start(QIODevice* device)
Uses the \a device as the QIODevice to transfer data.
\since 1.0
*/
/*!
\fn virtual QIODevice* QAbstractAudioOutput::start()
Returns a pointer to the QIODevice being used to handle
the data transfer. This QIODevice can be used to write() audio data directly.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::stop()
Stops the audio output.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::reset()
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::suspend()
Stops processing audio data, preserving buffered audio data.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::resume()
Resumes processing audio data after a suspend()
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::bytesFree() const
Returns the free space available in bytes in the audio buffer.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::periodSize() const
Returns the period size in bytes.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setBufferSize(int value)
Sets the audio buffer size to \a value in bytes.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::bufferSize() const
Returns the audio buffer size in bytes.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setNotifyInterval(int ms)
Sets the interval for notify() signal to be emitted. This is based on the \a ms
of audio data processed not on actual real-time. The resolution of the timer
is platform specific.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::notifyInterval() const
Returns the notify interval in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioOutput::processedUSecs() const
Returns the amount of audio data processed since start() was called in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioOutput::elapsedUSecs() const
Returns the milliseconds since start() was called, including time in Idle and suspend states.
\since 1.0
*/
/*!
\fn virtual QAudio::Error QAbstractAudioOutput::error() const
Returns the error state.
\since 1.0
*/
/*!
\fn virtual QAudio::State QAbstractAudioOutput::state() const
Returns the state of audio processing.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setFormat(const QAudioFormat& fmt)
Set the QAudioFormat to use to \a fmt.
Setting the format is only allowable while in QAudio::StoppedState.
\since 1.0
*/
/*!
\fn virtual QAudioFormat QAbstractAudioOutput::format() const
Returns the QAudioFormat being used.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setVolume(qreal volume)
Sets the volume.
Where \a volume is between 0.0 and 1.0.
\since 5.0
*/
/*!
\fn virtual qreal QAbstractAudioOutput::volume() const
Returns the volume in the range 0.0 and 1.0.
\since 5.0
*/
/*!
\fn QAbstractAudioOutput::errorChanged(QAudio::Error error)
This signal is emitted when the \a error state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioOutput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioOutput::notify()
This signal is emitted when x ms of audio data has been processed
the interval set by setNotifyInterval(x).
\since 1.0
*/
/*!
\class QAbstractAudioInput
\brief The QAbstractAudioInput class provides access for QAudioInput to access the audio
device provided by the plugin.
\since 1.0
\ingroup multimedia
\inmodule QtMultimedia
\internal
QAudioDeviceInput keeps an instance of QAbstractAudioInput and
routes calls to functions of the same name to QAbstractAudioInput.
This means that it is QAbstractAudioInput that implements the
audio functionality. For a description of the functionality, see
the QAudioInput class description.
\sa QAudioInput
*/
/*!
\fn virtual void QAbstractAudioInput::start(QIODevice* device)
Uses the \a device as the QIODevice to transfer data.
\since 1.0
*/
/*!
\fn virtual QIODevice* QAbstractAudioInput::start()
Returns a pointer to the QIODevice being used to handle
the data transfer. This QIODevice can be used to read() audio data directly.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::stop()
Stops the audio input.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::reset()
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::suspend()
Stops processing audio data, preserving buffered audio data.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::resume()
Resumes processing audio data after a suspend().
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::bytesReady() const
Returns the amount of audio data available to read in bytes.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::periodSize() const
Returns the period size in bytes.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::setBufferSize(int value)
Sets the audio buffer size to \a value in milliseconds.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::bufferSize() const
Returns the audio buffer size in milliseconds.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::setNotifyInterval(int ms)
Sets the interval for notify() signal to be emitted. This is based
on the \a ms of audio data processed not on actual real-time.
The resolution of the timer is platform specific.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::notifyInterval() const
Returns the notify interval in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioInput::processedUSecs() const
Returns the amount of audio data processed since start() was called in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioInput::elapsedUSecs() const
Returns the milliseconds since start() was called, including time in Idle and suspend states.
\since 1.0
*/
/*!
\fn virtual QAudio::Error QAbstractAudioInput::error() const
Returns the error state.
\since 1.0
*/
/*!
\fn virtual QAudio::State QAbstractAudioInput::state() const
Returns the state of audio processing.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::setFormat(const QAudioFormat& fmt)
Set the QAudioFormat to use to \a fmt.
Setting the format is only allowable while in QAudio::StoppedState.
\since 1.0
*/
/*!
\fn virtual QAudioFormat QAbstractAudioInput::format() const
Returns the QAudioFormat being used
\since 1.0
*/
/*!
\fn QAbstractAudioInput::errorChanged(QAudio::Error error)
This signal is emitted when the \a error state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioInput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioInput::notify()
This signal is emitted when x ms of audio data has been processed
the interval set by setNotifyInterval(x).
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudiosystem.cpp"

View File

@@ -0,0 +1,141 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOSYSTEM_H
#define QAUDIOSYSTEM_H
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include "qaudio.h"
#include "qaudioformat.h"
#include "qaudiodeviceinfo.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QAbstractAudioDeviceInfo : public QObject
{
Q_OBJECT
public:
virtual QAudioFormat preferredFormat() const = 0;
virtual bool isFormatSupported(const QAudioFormat &format) const = 0;
virtual QString deviceName() const = 0;
virtual QStringList supportedCodecs() = 0;
virtual QList<int> supportedSampleRates() = 0;
virtual QList<int> supportedChannelCounts() = 0;
virtual QList<int> supportedSampleSizes() = 0;
virtual QList<QAudioFormat::Endian> supportedByteOrders() = 0;
virtual QList<QAudioFormat::SampleType> supportedSampleTypes() = 0;
};
class Q_MULTIMEDIA_EXPORT QAbstractAudioOutput : public QObject
{
Q_OBJECT
public:
virtual void start(QIODevice *device) = 0;
virtual QIODevice* start() = 0;
virtual void stop() = 0;
virtual void reset() = 0;
virtual void suspend() = 0;
virtual void resume() = 0;
virtual int bytesFree() const = 0;
virtual int periodSize() const = 0;
virtual void setBufferSize(int value) = 0;
virtual int bufferSize() const = 0;
virtual void setNotifyInterval(int milliSeconds) = 0;
virtual int notifyInterval() const = 0;
virtual qint64 processedUSecs() const = 0;
virtual qint64 elapsedUSecs() const = 0;
virtual QAudio::Error error() const = 0;
virtual QAudio::State state() const = 0;
virtual void setFormat(const QAudioFormat& fmt) = 0;
virtual QAudioFormat format() const = 0;
virtual void setVolume(qreal) {}
virtual qreal volume() const { return 1.0; }
Q_SIGNALS:
void errorChanged(QAudio::Error);
void stateChanged(QAudio::State);
void notify();
};
class Q_MULTIMEDIA_EXPORT QAbstractAudioInput : public QObject
{
Q_OBJECT
public:
virtual void start(QIODevice *device) = 0;
virtual QIODevice* start() = 0;
virtual void stop() = 0;
virtual void reset() = 0;
virtual void suspend() = 0;
virtual void resume() = 0;
virtual int bytesReady() const = 0;
virtual int periodSize() const = 0;
virtual void setBufferSize(int value) = 0;
virtual int bufferSize() const = 0;
virtual void setNotifyInterval(int milliSeconds) = 0;
virtual int notifyInterval() const = 0;
virtual qint64 processedUSecs() const = 0;
virtual qint64 elapsedUSecs() const = 0;
virtual QAudio::Error error() const = 0;
virtual QAudio::State state() const = 0;
virtual void setFormat(const QAudioFormat& fmt) = 0;
virtual QAudioFormat format() const = 0;
Q_SIGNALS:
void errorChanged(QAudio::Error);
void stateChanged(QAudio::State);
void notify();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOSYSTEM_H

View File

@@ -0,0 +1,143 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudiosystemplugin.h"
QT_BEGIN_NAMESPACE
/*!
\class QAudioSystemPlugin
\brief The QAudioSystemPlugin class provides an abstract base for audio plugins.
\since 1.0
\ingroup multimedia
\inmodule QtMultimedia
\internal
Writing a audio plugin is achieved by subclassing this base class,
reimplementing the pure virtual functions keys(), availableDevices(),
createInput(), createOutput() and createDeviceInfo() then exporting
the class with the Q_EXPORT_PLUGIN2() macro.
Unit tests are available to help in debugging new plugins.
\sa QAbstractAudioDeviceInfo, QAbstractAudioOutput, QAbstractAudioInput
Qt supports win32, linux(alsa) and Mac OS X standard (builtin to the
QtMultimedia library at compile time).
You can support other backends other than these predefined ones by
creating a plugin subclassing QAudioSystemPlugin, QAbstractAudioDeviceInfo,
QAbstractAudioOutput and QAbstractAudioInput.
Add "default" to your list of keys() available to override the default
audio device to be provided by your plugin.
-audio-backend configure option will force compiling in of the builtin backend
into the QtMultimedia library at compile time. This is automatic by default
and will only be compiled into the library if the dependencies are installed.
eg. alsa-devel package installed for linux.
If the builtin backend is not compiled into the QtMultimedia library and
no audio plugins are available a fallback dummy backend will be used.
This should print out warnings if this is the case when you try and use QAudioInput or QAudioOutput. To fix this problem
reconfigure Qt using -audio-backend or create your own plugin with a default
key to always override the dummy fallback. The easiest way to determine
if you have only a dummy backend is to get a list of available audio devices.
QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).size() = 0 (dummy backend)
*/
/*!
Construct a new audio plugin with \a parent.
This is invoked automatically by the Q_EXPORT_PLUGIN2() macro.
*/
QAudioSystemPlugin::QAudioSystemPlugin(QObject* parent) :
QObject(parent)
{}
/*!
Destroy the audio plugin
You never have to call this explicitly. Qt destroys a plugin automatically when it is no longer used.
*/
QAudioSystemPlugin::~QAudioSystemPlugin()
{}
/*!
\fn QStringList QAudioSystemPlugin::keys() const
Returns the list of device identifiers this plugin supports.
\since 1.0
*/
/*!
\fn QList<QByteArray> QAudioSystemPlugin::availableDevices(QAudio::Mode mode) const
Returns a list of available audio devices for \a mode
\since 1.0
*/
/*!
\fn QAbstractAudioInput* QAudioSystemPlugin::createInput(const QByteArray& device)
Returns a pointer to a QAbstractAudioInput created using \a device identifier
\since 1.0
*/
/*!
\fn QAbstractAudioOutput* QAudioSystemPlugin::createOutput(const QByteArray& device)
Returns a pointer to a QAbstractAudioOutput created using \a device identifier
\since 1.0
*/
/*!
\fn QAbstractAudioDeviceInfo* QAudioSystemPlugin::createDeviceInfo(const QByteArray& device, QAudio::Mode mode)
Returns a pointer to a QAbstractAudioDeviceInfo created using \a device and \a mode
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudiosystemplugin.cpp"

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOSYSTEMPLUGIN_H
#define QAUDIOSYSTEMPLUGIN_H
#include <QtCore/qstring.h>
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <qtmultimediadefs.h>
#include <qtmedianamespace.h>
#include "qaudioformat.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
struct Q_MULTIMEDIA_EXPORT QAudioSystemFactoryInterface : public QFactoryInterface
{
virtual QList<QByteArray> availableDevices(QAudio::Mode) const = 0;
virtual QAbstractAudioInput* createInput(const QByteArray& device) = 0;
virtual QAbstractAudioOutput* createOutput(const QByteArray& device) = 0;
virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0;
};
#define QAudioSystemFactoryInterface_iid \
"com.nokia.qt.QAudioSystemFactoryInterface"
Q_DECLARE_INTERFACE(QAudioSystemFactoryInterface, QAudioSystemFactoryInterface_iid)
class Q_MULTIMEDIA_EXPORT QAudioSystemPlugin : public QObject, public QAudioSystemFactoryInterface
{
Q_OBJECT
Q_INTERFACES(QAudioSystemFactoryInterface:QFactoryInterface)
public:
QAudioSystemPlugin(QObject *parent = 0);
~QAudioSystemPlugin();
virtual QStringList keys() const = 0;
virtual QList<QByteArray> availableDevices(QAudio::Mode) const = 0;
virtual QAbstractAudioInput* createInput(const QByteArray& device) = 0;
virtual QAbstractAudioOutput* createOutput(const QByteArray& device) = 0;
virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOSYSTEMPLUGIN_H

View File

@@ -0,0 +1,36 @@
INCLUDEPATH += effects
unix:!mac {
contains(config_test_pulseaudio, yes) {
CONFIG += link_pkgconfig
PKGCONFIG += libpulse
DEFINES += QT_MULTIMEDIA_PULSEAUDIO
PRIVATE_HEADERS += effects/qsoundeffect_pulse_p.h
SOURCES += effects/qsoundeffect_pulse_p.cpp
!maemo*:DEFINES += QTM_PULSEAUDIO_DEFAULTBUFFER
} else {
DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER
PRIVATE_HEADERS += effects/qsoundeffect_qmedia_p.h
SOURCES += effects/qsoundeffect_qmedia_p.cpp
}
} else:!qpa {
PRIVATE_HEADERS += effects/qsoundeffect_qsound_p.h
SOURCES += effects/qsoundeffect_qsound_p.cpp
} else {
DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER
PRIVATE_HEADERS += effects/qsoundeffect_qmedia_p.h
SOURCES += effects/qsoundeffect_qmedia_p.cpp
}
PRIVATE_HEADERS += \
effects/qsoundeffect_p.h \
effects/qwavedecoder_p.h \
effects/qsamplecache_p.h
SOURCES += \
effects/qsoundeffect.cpp \
effects/qwavedecoder_p.cpp \
effects/qsamplecache_p.cpp
HEADERS +=

View File

@@ -0,0 +1,398 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qsamplecache_p.h"
#include "qwavedecoder_p.h"
#include <QtNetwork>
//#define QT_SAMPLECACHE_DEBUG
QT_BEGIN_NAMESPACE
/*!
\class QSampleCache
\internal
When you want to get a sound sample data, you need to request the QSample reference from QSampleCache.
\since 1.1
\code
QSample *m_sample; // class member.
private Q_SLOTS:
void decoderError();
void sampleReady();
\endcode
\code
Q_GLOBAL_STATIC(QSampleCache, sampleCache) //declare a singleton manager
\endcode
\code
m_sample = sampleCache()->requestSample(url);
switch(m_sample->state()) {
case QSample::Ready:
sampleReady();
break;
case QSample::Error:
decoderError();
break;
default:
connect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
connect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
break;
}
\endcode
When you no longer need the sound sample data, you need to release it:
\code
if (m_sample) {
m_sample->release();
m_sample = 0;
}
\endcode
*/
QSampleCache::QSampleCache()
: m_networkAccessManager(0)
, m_mutex(QMutex::Recursive)
, m_capacity(0)
, m_usage(0)
{
m_loadingThread.setObjectName(QLatin1String("QSampleCache::LoadingThread"));
}
QNetworkAccessManager& QSampleCache::networkAccessManager()
{
if (!m_networkAccessManager)
m_networkAccessManager = new QNetworkAccessManager();
return *m_networkAccessManager;
}
QSampleCache::~QSampleCache()
{
QMutexLocker m(&m_mutex);
m_loadingThread.quit();
m_loadingThread.wait();
// Killing the loading thread means that no samples can be
// deleted using deleteLater. And some samples that had deleteLater
// already called won't have been processed (m_staleSamples)
foreach (QSample* sample, m_samples)
delete sample;
foreach (QSample* sample, m_staleSamples)
delete sample; // deleting a sample does affect the m_staleSamples list, but foreach copies it
delete m_networkAccessManager;
}
QSample* QSampleCache::requestSample(const QUrl& url)
{
if (!m_loadingThread.isRunning())
m_loadingThread.start();
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: request sample [" << url << "]";
#endif
QMutexLocker locker(&m_mutex);
QMap<QUrl, QSample*>::iterator it = m_samples.find(url);
QSample* sample;
if (it == m_samples.end()) {
sample = new QSample(url, this);
m_samples.insert(url, sample);
sample->moveToThread(&m_loadingThread);
} else {
sample = *it;
}
sample->addRef();
locker.unlock();
sample->loadIfNecessary();
return sample;
}
void QSampleCache::setCapacity(qint64 capacity)
{
QMutexLocker locker(&m_mutex);
if (m_capacity == capacity)
return;
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: capacity changes from " << m_capacity << "to " << capacity;
#endif
if (m_capacity > 0 && capacity <= 0) { //memory management strategy changed
for (QMap<QUrl, QSample*>::iterator it = m_samples.begin(); it != m_samples.end();) {
QSample* sample = *it;
if (sample->m_ref == 0) {
unloadSample(sample);
it = m_samples.erase(it);
} else
it++;
}
}
m_capacity = capacity;
refresh(0);
}
// Called locked
void QSampleCache::unloadSample(QSample *sample)
{
m_usage -= sample->m_soundData.size();
m_staleSamples.insert(sample);
sample->deleteLater();
}
// Called in both threads
void QSampleCache::refresh(qint64 usageChange)
{
QMutexLocker locker(&m_mutex);
m_usage += usageChange;
if (m_capacity <= 0 || m_usage <= m_capacity)
return;
#ifdef QT_SAMPLECACHE_DEBUG
qint64 recoveredSize = 0;
#endif
//free unused samples to keep usage under capacity limit.
for (QMap<QUrl, QSample*>::iterator it = m_samples.begin(); it != m_samples.end();) {
QSample* sample = *it;
if (sample->m_ref > 0) {
++it;
continue;
}
#ifdef QT_SAMPLECACHE_DEBUG
recoveredSize += sample->m_soundData.size();
#endif
unloadSample(sample);
it = m_samples.erase(it);
if (m_usage <= m_capacity)
return;
}
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: refresh(" << usageChange
<< ") recovered size =" << recoveredSize
<< "new usage =" << m_usage;
#endif
if (m_usage > m_capacity)
qWarning() << "QSampleCache: usage[" << m_usage << " out of limit[" << m_capacity << "]";
}
// Called in both threads
void QSampleCache::removeUnreferencedSample(QSample *sample)
{
QMutexLocker m(&m_mutex);
m_staleSamples.remove(sample);
}
// Called in loader thread (since this lives in that thread)
// Also called from application thread after loader thread dies.
QSample::~QSample()
{
// Remove ourselves from our parent
m_parent->removeUnreferencedSample(this);
QMutexLocker locker(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "~QSample" << this << ": deleted [" << m_url << "]" << QThread::currentThread();
#endif
cleanup();
}
// Called in application thread
void QSample::loadIfNecessary()
{
QMutexLocker locker(&m_mutex);
if (m_state == QSample::Error || m_state == QSample::Creating) {
m_state = QSample::Loading;
QMetaObject::invokeMethod(this, "load", Qt::QueuedConnection);
}
}
// Called in both threads
bool QSampleCache::notifyUnreferencedSample(QSample* sample)
{
QMutexLocker locker(&m_mutex);
if (m_capacity > 0)
return false;
m_samples.remove(sample->m_url);
m_staleSamples.insert(sample);
sample->deleteLater();
return true;
}
// Called in application threadd
void QSample::release()
{
QMutexLocker locker(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "Sample:: release" << this << QThread::currentThread() << m_ref;
#endif
m_ref--;
if (m_ref == 0)
m_parent->notifyUnreferencedSample(this);
}
// Called in dtor and when stream is loaded
// must be called locked.
void QSample::cleanup()
{
delete m_waveDecoder;
delete m_stream;
m_waveDecoder = 0;
m_stream = 0;
}
// Called in application thread
void QSample::addRef()
{
m_ref++;
}
// Called in loading thread
void QSample::readSample()
{
Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String("QSampleCache::LoadingThread"));
QMutexLocker m(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: readSample";
#endif
qint64 read = m_waveDecoder->read(m_soundData.data() + m_sampleReadLength,
qMin(m_waveDecoder->bytesAvailable(),
qint64(m_waveDecoder->size() - m_sampleReadLength)));
if (read > 0)
m_sampleReadLength += read;
if (m_sampleReadLength < m_waveDecoder->size())
return;
Q_ASSERT(m_sampleReadLength == qint64(m_soundData.size()));
onReady();
}
// Called in loading thread
void QSample::decoderReady()
{
Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String("QSampleCache::LoadingThread"));
QMutexLocker m(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: decoder ready";
#endif
m_parent->refresh(m_waveDecoder->size());
m_soundData.resize(m_waveDecoder->size());
m_sampleReadLength = 0;
qint64 read = m_waveDecoder->read(m_soundData.data(), m_waveDecoder->size());
if (read > 0)
m_sampleReadLength += read;
if (m_sampleReadLength >= m_waveDecoder->size())
onReady();
}
// Called in all threads
QSample::State QSample::state() const
{
QMutexLocker m(&m_mutex);
return m_state;
}
// Called in loading thread
// Essentially a second ctor, doesn't need locks (?)
void QSample::load()
{
Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String("QSampleCache::LoadingThread"));
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: load [" << m_url << "]";
#endif
m_stream = m_parent->networkAccessManager().get(QNetworkRequest(m_url));
connect(m_stream, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(decoderError()));
m_waveDecoder = new QWaveDecoder(m_stream);
connect(m_waveDecoder, SIGNAL(formatKnown()), SLOT(decoderReady()));
connect(m_waveDecoder, SIGNAL(invalidFormat()), SLOT(decoderError()));
connect(m_waveDecoder, SIGNAL(readyRead()), SLOT(readSample()));
}
// Called in loading thread
void QSample::decoderError()
{
Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String("QSampleCache::LoadingThread"));
QMutexLocker m(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: decoder error";
#endif
cleanup();
m_state = QSample::Error;
emit error();
}
// Called in loading thread from decoder when sample is done. Locked already.
void QSample::onReady()
{
Q_ASSERT(QThread::currentThread()->objectName() == QLatin1String("QSampleCache::LoadingThread"));
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: load ready";
#endif
m_audioFormat = m_waveDecoder->audioFormat();
cleanup();
m_state = QSample::Ready;
emit ready();
}
// Called in application thread, then moved to loader thread
QSample::QSample(const QUrl& url, QSampleCache *parent)
: m_parent(parent)
, m_stream(0)
, m_waveDecoder(0)
, m_url(url)
, m_sampleReadLength(0)
, m_state(Creating)
, m_ref(0)
{
}
QT_END_NAMESPACE
#include "moc_qsamplecache_p.cpp"

View File

@@ -0,0 +1,161 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QSAMPLECACHE_P_H
#define QSAMPLECACHE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qobject.h>
#include <QtCore/qthread.h>
#include <QtCore/qurl.h>
#include <QtCore/qmutex.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QNetworkAccessManager;
class QSampleCache;
class QWaveDecoder;
// Lives in application thread
class QSample : public QObject
{
Q_OBJECT
public:
friend class QSampleCache;
enum State
{
Creating,
Loading,
Error,
Ready,
};
State state() const;
// These are not (currently) locked because they are only meant to be called after these
// variables are updated to their final states
const QByteArray& data() const { Q_ASSERT(state() == Ready); return m_soundData; }
const QAudioFormat& format() const { Q_ASSERT(state() == Ready); return m_audioFormat; }
void release();
Q_SIGNALS:
void error();
void ready();
protected:
QSample(const QUrl& url, QSampleCache *parent);
private Q_SLOTS:
void load();
void decoderError();
void readSample();
void decoderReady();
private:
void onReady();
void cleanup();
void addRef();
void loadIfNecessary();
QSample();
~QSample();
mutable QMutex m_mutex;
QSampleCache *m_parent;
QByteArray m_soundData;
QAudioFormat m_audioFormat;
QIODevice *m_stream;
QWaveDecoder *m_waveDecoder;
QUrl m_url;
qint64 m_sampleReadLength;
State m_state;
int m_ref;
};
class QSampleCache
{
public:
friend class QSample;
QSampleCache();
~QSampleCache();
QSample* requestSample(const QUrl& url);
void setCapacity(qint64 capacity);
private:
QMap<QUrl, QSample*> m_samples;
QSet<QSample*> m_staleSamples;
QNetworkAccessManager *m_networkAccessManager;
QMutex m_mutex;
qint64 m_capacity;
qint64 m_usage;
QThread m_loadingThread;
QNetworkAccessManager& networkAccessManager();
void refresh(qint64 usageChange);
bool notifyUnreferencedSample(QSample* sample);
void removeUnreferencedSample(QSample* sample);
void unloadSample(QSample* sample);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSAMPLECACHE_P_H

View File

@@ -0,0 +1,301 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qsoundeffect_p.h"
#if defined(QT_MULTIMEDIA_PULSEAUDIO)
#include "qsoundeffect_pulse_p.h"
#elif(QT_MULTIMEDIA_QMEDIAPLAYER)
#include "qsoundeffect_qmedia_p.h"
#else
#include "qsoundeffect_qsound_p.h"
#endif
QT_BEGIN_NAMESPACE
/*!
\qmlclass SoundEffect QSoundEffect
\brief The SoundEffect element provides a way to play sound effects in QML.
\since 1.0
\inmodule QtMultimedia
This element is part of the \bold{QtMultimedia 4.0} module.
The following example plays a WAV file on mouse click.
\snippet doc/src/snippets/multimedia-snippets/soundeffect.qml complete snippet
*/
/*!
\qmlproperty url SoundEffect::source
\since 1.0
This property provides a way to control the sound to play.
*/
/*!
\qmlproperty int SoundEffect::loops
\since 1.0
This property provides a way to control the number of times to repeat the sound on each play().
Set to -1 (infinite) to enable infinite loop.
*/
/*!
\qmlproperty qreal SoundEffect::volume
\since 1.0
This property holds the volume of the playback, from 0.0 (silent) to 1.0 (maximum volume).
Note: Currently this has no effect on Mac OS X.
*/
/*!
\qmlproperty bool SoundEffect::muted
\since 1.0
This property provides a way to control muting.
*/
/*!
\qmlproperty bool SoundEffect::playing
\since 1.1
This property indicates if the soundeffect is playing or not.
*/
/*!
\qmlproperty int SoundEffect::status
\since 1.0
This property indicates the following status of the soundeffect.
Null: no source has been set or is null.
Loading: the soundeffect is trying to load the source.
Ready: the source is loaded and ready for play.
Error: some error happened during operation, such as failure of loading the source.
*/
/*!
\qmlsignal SoundEffect::sourceChanged()
\since 1.0
This handler is called when the source has changed.
*/
/*!
\qmlsignal SoundEffect::loopsChanged()
\since 1.0
This handler is called when the number of loops has changed.
*/
/*!
\qmlsignal SoundEffect::volumeChanged()
\since 1.0
This handler is called when the volume has changed.
*/
/*!
\qmlsignal SoundEffect::mutedChanged()
\since 1.0
This handler is called when the mute state has changed.
*/
/*!
\qmlsignal SoundEffect::playingChanged()
\since 1.0
This handler is called when the playing property has changed.
*/
/*!
\qmlsignal SoundEffect::statusChanged()
This handler is called when the status property has changed.
\since 1.0
*/
/*!
\internal
\since 1.0
*/
QSoundEffect::QSoundEffect(QObject *parent) :
QObject(parent)
{
d = new QSoundEffectPrivate(this);
connect(d, SIGNAL(volumeChanged()), SIGNAL(volumeChanged()));
connect(d, SIGNAL(mutedChanged()), SIGNAL(mutedChanged()));
connect(d, SIGNAL(loadedChanged()), SIGNAL(loadedChanged()));
connect(d, SIGNAL(playingChanged()), SIGNAL(playingChanged()));
connect(d, SIGNAL(statusChanged()), SIGNAL(statusChanged()));
}
QSoundEffect::~QSoundEffect()
{
d->deleteLater();
}
QStringList QSoundEffect::supportedMimeTypes()
{
return QSoundEffectPrivate::supportedMimeTypes();
}
QUrl QSoundEffect::source() const
{
return d->source();
}
void QSoundEffect::setSource(const QUrl &url)
{
if (d->source() == url)
return;
d->setSource(url);
emit sourceChanged();
}
int QSoundEffect::loopCount() const
{
return d->loopCount();
}
void QSoundEffect::setLoopCount(int loopCount)
{
if (loopCount < 0 && loopCount != Infinite) {
qWarning("SoundEffect: loops should be SoundEffect.Infinite, 0 or positive integer");
return;
}
if (loopCount == 0)
loopCount = 1;
if (d->loopCount() == loopCount)
return;
d->setLoopCount(loopCount);
emit loopCountChanged();
}
qreal QSoundEffect::volume() const
{
return qreal(d->volume()) / 100;
}
void QSoundEffect::setVolume(qreal volume)
{
if (volume < 0 || volume > 1) {
qWarning("SoundEffect: volume should be between 0.0 and 1.0");
return;
}
int iVolume = qRound(volume * 100);
if (d->volume() == iVolume)
return;
d->setVolume(iVolume);
}
bool QSoundEffect::isMuted() const
{
return d->isMuted();
}
void QSoundEffect::setMuted(bool muted)
{
if (d->isMuted() == muted)
return;
d->setMuted(muted);
}
bool QSoundEffect::isLoaded() const
{
return d->isLoaded();
}
/*!
\qmlmethod SoundEffect::play()
Start playback of the sound effect, looping the effect for the number of
times as specificed in the loops property.
This is the default method for SoundEffect.
\snippet doc/src/snippets/multimedia-snippets/soundeffect.qml play sound on click
\since 1.0
*/
void QSoundEffect::play()
{
d->play();
}
bool QSoundEffect::isPlaying() const
{
return d->isPlaying();
}
QSoundEffect::Status QSoundEffect::status() const
{
return d->status();
}
/*!
\qmlmethod SoundEffect::stop()
Stop current playback.
Note that if the backend is PulseAudio, due to the limitation of the underlying API,
tis stop will only prevent next looping but will not be able to stop current playback immediately.
\since 1.0
*/
void QSoundEffect::stop()
{
d->stop();
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_p.cpp"

View File

@@ -0,0 +1,143 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_P_H
#define QSOUNDEFFECT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <qtmultimediadefs.h>
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QSoundEffectPrivate;
class Q_MULTIMEDIA_EXPORT QSoundEffect : public QObject
{
Q_OBJECT
Q_CLASSINFO("DefaultMethod", "play()")
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
Q_PROPERTY(bool playing READ isPlaying NOTIFY playingChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_ENUMS(Loop)
Q_ENUMS(Status)
public:
enum Loop
{
Infinite = -2,
};
enum Status
{
Null,
Loading,
Ready,
Error
};
explicit QSoundEffect(QObject *parent = 0);
~QSoundEffect();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
qreal volume() const;
void setVolume(qreal volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying() const;
Status status() const;
Q_SIGNALS:
void sourceChanged();
void loopCountChanged();
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
public Q_SLOTS:
void play();
void stop();
private:
Q_DISABLE_COPY(QSoundEffect)
QSoundEffectPrivate* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_H

View File

@@ -0,0 +1,957 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <QtCore/qcoreapplication.h>
#include <qaudioformat.h>
#include <QtNetwork>
#include <QTime>
#include "qsoundeffect_pulse_p.h"
#if defined(Q_WS_MAEMO_6)
#include <pulse/ext-stream-restore.h>
#endif
#include <unistd.h>
//#define QT_PA_DEBUG
#ifndef QTM_PULSEAUDIO_DEFAULTBUFFER
#define QT_PA_STREAM_BUFFER_SIZE_MAX (1024 * 64) //64KB is a trade-off for balancing control latency and uploading overhead
#endif
QT_BEGIN_NAMESPACE
namespace
{
inline pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format)
{
pa_sample_spec spec;
spec.rate = format.frequency();
spec.channels = format.channels();
if (format.sampleSize() == 8)
spec.format = PA_SAMPLE_U8;
else if (format.sampleSize() == 16) {
switch (format.byteOrder()) {
case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S16BE; break;
case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S16LE; break;
}
}
else if (format.sampleSize() == 32) {
switch (format.byteOrder()) {
case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S32BE; break;
case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S32LE; break;
}
}
return spec;
}
class PulseDaemon : public QObject
{
Q_OBJECT
public:
PulseDaemon(): m_prepared(false)
{
prepare();
}
~PulseDaemon()
{
if (m_prepared)
release();
}
inline void lock()
{
pa_threaded_mainloop_lock(m_mainLoop);
}
inline void unlock()
{
pa_threaded_mainloop_unlock(m_mainLoop);
}
inline pa_context *context() const
{
return m_context;
}
inline pa_cvolume * calcVolume(pa_cvolume *dest, int soundEffectVolume)
{
dest->channels = 2;
dest->values[0] = dest->values[1] = m_vol * soundEffectVolume / 100;
return dest;
}
void updateStatus(const pa_cvolume& volume)
{
if (m_vol != pa_cvolume_max(&volume)) {
m_vol = pa_cvolume_max(&volume);
emit volumeChanged();
}
}
Q_SIGNALS:
void contextReady();
void volumeChanged();
private:
void prepare()
{
m_vol = PA_VOLUME_NORM;
m_mainLoop = pa_threaded_mainloop_new();
if (m_mainLoop == 0) {
qWarning("PulseAudioService: unable to create pulseaudio mainloop");
return;
}
if (pa_threaded_mainloop_start(m_mainLoop) != 0) {
qWarning("PulseAudioService: unable to start pulseaudio mainloop");
pa_threaded_mainloop_free(m_mainLoop);
return;
}
m_mainLoopApi = pa_threaded_mainloop_get_api(m_mainLoop);
lock();
m_context = pa_context_new(m_mainLoopApi, QString(QLatin1String("QtPulseAudio:%1")).arg(::getpid()).toAscii().constData());
pa_context_set_state_callback(m_context, context_state_callback, this);
if (m_context == 0) {
qWarning("PulseAudioService: Unable to create new pulseaudio context");
pa_threaded_mainloop_free(m_mainLoop);
return;
}
if (pa_context_connect(m_context, 0, (pa_context_flags_t)0, 0) < 0) {
qWarning("PulseAudioService: pa_context_connect() failed");
pa_context_unref(m_context);
pa_threaded_mainloop_free(m_mainLoop);
return;
}
unlock();
m_prepared = true;
}
void release()
{
if (!m_prepared) return;
pa_threaded_mainloop_stop(m_mainLoop);
pa_threaded_mainloop_free(m_mainLoop);
m_prepared = false;
}
static void context_state_callback(pa_context *c, void *userdata)
{
PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata);
switch (pa_context_get_state(c)) {
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
case PA_CONTEXT_READY:
#if defined(Q_WS_MAEMO_6)
pa_ext_stream_restore_read(c, &stream_restore_info_callback, self);
pa_ext_stream_restore_set_subscribe_cb(c, &stream_restore_monitor_callback, self);
pa_ext_stream_restore_subscribe(c, 1, 0, self);
#endif
QMetaObject::invokeMethod(self, "contextReady", Qt::QueuedConnection);
break;
default:
break;
}
}
#if defined(Q_WS_MAEMO_6)
static void stream_restore_monitor_callback(pa_context *c, void *userdata)
{
PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata);
pa_ext_stream_restore_read(c, &stream_restore_info_callback, self);
}
static void stream_restore_info_callback(pa_context *c,
const pa_ext_stream_restore_info *info,
int eol, void *userdata)
{
Q_UNUSED(c)
PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata);
if (!eol) {
if (QString(info->name).startsWith(QLatin1String("sink-input-by-media-role:x-maemo"))) {
#ifdef QT_PA_DEBUG
qDebug() << "x-maemo volume =(" << info->volume.values[0] * 100 / PA_VOLUME_NORM << ","
<< info->volume.values[1] * 100 / PA_VOLUME_NORM << "), "
<< "mute = " << info->mute;
#endif
self->updateStatus(info->volume);
}
}
}
#endif
pa_volume_t m_vol;
bool m_prepared;
pa_context *m_context;
pa_threaded_mainloop *m_mainLoop;
pa_mainloop_api *m_mainLoopApi;
};
}
Q_GLOBAL_STATIC(PulseDaemon, daemon)
Q_GLOBAL_STATIC(QSampleCache, sampleCache)
namespace
{
class PulseDaemonLocker
{
public:
PulseDaemonLocker()
{
daemon()->lock();
}
~PulseDaemonLocker()
{
daemon()->unlock();
}
};
}
QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
QObject(parent),
m_pulseStream(0),
m_sinkInputId(-1),
m_emptying(false),
m_sampleReady(false),
m_playing(false),
m_status(QSoundEffect::Null),
m_muted(false),
m_playQueued(false),
m_stopping(false),
m_volume(100),
m_loopCount(1),
m_runningCount(0),
m_sample(0) ,
m_position(0)
{
pa_sample_spec_init(&m_pulseSpec);
}
QSoundEffectPrivate::~QSoundEffectPrivate()
{
unloadPulseStream();
if (m_sample)
m_sample->release();
}
QStringList QSoundEffectPrivate::supportedMimeTypes()
{
QStringList supportedTypes;
supportedTypes << QLatin1String("audio/x-wav") << QLatin1String("audio/vnd.wave") ;
return supportedTypes;
}
QUrl QSoundEffectPrivate::source() const
{
return m_source;
}
void QSoundEffectPrivate::setSource(const QUrl &url)
{
Q_ASSERT(m_source != url);
#ifdef QT_PA_DEBUG
qDebug() << this << "setSource =" << url;
#endif
stop();
if (m_sample) {
if (!m_sampleReady) {
disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
disconnect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
}
m_sample->release();
m_sample = 0;
}
m_source = url;
m_sampleReady = false;
PulseDaemonLocker locker;
m_runningCount = 0;
if (m_pulseStream && !pa_stream_is_corked(m_pulseStream)) {
pa_stream_set_write_callback(m_pulseStream, 0, 0);
pa_stream_set_underflow_callback(m_pulseStream, 0, 0);
pa_operation_unref(pa_stream_cork(m_pulseStream, 1, 0, 0));
}
setPlaying(false);
if (url.isEmpty()) {
setStatus(QSoundEffect::Null);
return;
}
setStatus(QSoundEffect::Loading);
m_sample = sampleCache()->requestSample(url);
connect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
connect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
switch(m_sample->state()) {
case QSample::Ready:
sampleReady();
break;
case QSample::Error:
decoderError();
break;
default:
break;
}
}
int QSoundEffectPrivate::loopCount() const
{
return m_loopCount;
}
void QSoundEffectPrivate::setLoopCount(int loopCount)
{
if (loopCount == 0)
loopCount = 1;
m_loopCount = loopCount;
}
int QSoundEffectPrivate::volume() const
{
return m_volume;
}
void QSoundEffectPrivate::setVolume(int volume)
{
m_volume = volume;
emit volumeChanged();
updateVolume();
}
void QSoundEffectPrivate::updateVolume()
{
if (m_sinkInputId < 0)
return;
PulseDaemonLocker locker;
pa_cvolume volume;
pa_operation_unref(pa_context_set_sink_input_volume(daemon()->context(), m_sinkInputId, daemon()->calcVolume(&volume, m_volume), setvolume_callback, this));
Q_ASSERT(pa_cvolume_valid(&volume));
#ifdef QT_PA_DEBUG
qDebug() << this << "updateVolume =" << pa_cvolume_max(&volume);
#endif
}
bool QSoundEffectPrivate::isMuted() const
{
return m_muted;
}
void QSoundEffectPrivate::setMuted(bool muted)
{
m_muted = muted;
emit mutedChanged();
updateMuted();
}
void QSoundEffectPrivate::updateMuted()
{
if (m_sinkInputId < 0)
return;
PulseDaemonLocker locker;
pa_operation_unref(pa_context_set_sink_input_mute(daemon()->context(), m_sinkInputId, m_muted, setmuted_callback, this));
#ifdef QT_PA_DEBUG
qDebug() << this << "updateMuted = " << daemon()->calcMuted(m_muted);
#endif
}
bool QSoundEffectPrivate::isLoaded() const
{
return m_status == QSoundEffect::Ready;
}
bool QSoundEffectPrivate::isPlaying() const
{
return m_playing;
}
QSoundEffect::Status QSoundEffectPrivate::status() const
{
return m_status;
}
void QSoundEffectPrivate::setPlaying(bool playing)
{
#ifdef QT_PA_DEBUG
qDebug() << this << "setPlaying(" << playing << ")";
#endif
if (m_playing == playing)
return;
if (!playing)
m_playQueued = false;
m_playing = playing;
emit playingChanged();
}
void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
{
#ifdef QT_PA_DEBUG
qDebug() << this << "setStatus" << status;
#endif
if (m_status == status)
return;
bool oldLoaded = isLoaded();
m_status = status;
emit statusChanged();
if (oldLoaded != isLoaded())
emit loadedChanged();
}
void QSoundEffectPrivate::play()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "play";
#endif
if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error || m_playQueued)
return;
PulseDaemonLocker locker;
if (!m_sampleReady || m_stopping || m_emptying) {
#ifdef QT_PA_DEBUG
qDebug() << this << "play deferred";
#endif
m_playQueued = true;
} else {
if (m_playing) { //restart playing from the beginning
#ifdef QT_PA_DEBUG
qDebug() << this << "restart playing";
#endif
m_runningCount = 0;
m_playQueued = true;
Q_ASSERT(m_pulseStream);
emptyStream();
return;
}
m_runningCount = m_loopCount;
playSample();
}
setPlaying(true);
}
void QSoundEffectPrivate::emptyStream()
{
m_emptying = true;
pa_stream_set_write_callback(m_pulseStream, 0, this);
pa_stream_set_underflow_callback(m_pulseStream, 0, this);
pa_operation_unref(pa_stream_flush(m_pulseStream, stream_flush_callback, this));
}
void QSoundEffectPrivate::emptyComplete()
{
PulseDaemonLocker locker;
m_emptying = false;
pa_operation_unref(pa_stream_cork(m_pulseStream, 1, stream_cork_callback, this));
}
void QSoundEffectPrivate::sampleReady()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "sampleReady";
#endif
disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
disconnect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
pa_sample_spec newFormatSpec = audioFormatToSampleSpec(m_sample->format());
if (m_pulseStream && (memcmp(&m_pulseSpec, &newFormatSpec, sizeof(m_pulseSpec)) != 0)) {
unloadPulseStream();
}
m_pulseSpec = newFormatSpec;
m_sampleReady = true;
m_position = 0;
if (m_name.isNull())
m_name = QString(QLatin1String("QtPulseSample-%1-%2")).arg(::getpid()).arg(quintptr(this)).toUtf8();
PulseDaemonLocker locker;
if (m_pulseStream) {
#ifdef QT_PA_DEBUG
qDebug() << this << "reuse existing pulsestream";
#endif
#ifdef QTM_PULSEAUDIO_DEFAULTBUFFER
const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(m_pulseStream);
if (bufferAttr->prebuf > uint32_t(m_sample->data().size())) {
pa_buffer_attr newBufferAttr;
newBufferAttr = *bufferAttr;
newBufferAttr.prebuf = m_sample->data().size();
pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, this);
} else {
streamReady();
}
#else
const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(m_pulseStream);
if (bufferAttr->tlength < m_sample->data().size() && bufferAttr->tlength < QT_PA_STREAM_BUFFER_SIZE_MAX) {
pa_buffer_attr newBufferAttr;
newBufferAttr.maxlength = -1;
newBufferAttr.tlength = qMin(m_sample->data().size(), QT_PA_STREAM_BUFFER_SIZE_MAX);
newBufferAttr.minreq = bufferAttr->tlength / 2;
newBufferAttr.prebuf = -1;
newBufferAttr.fragsize = -1;
pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_reset_buffer_callback, this);
} else if (bufferAttr->prebuf > uint32_t(m_sample->data().size())) {
pa_buffer_attr newBufferAttr;
newBufferAttr = *bufferAttr;
newBufferAttr.prebuf = m_sample->data().size();
pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, this);
} else {
streamReady();
}
#endif
} else {
if (pa_context_get_state(daemon()->context()) != PA_CONTEXT_READY) {
connect(daemon(), SIGNAL(contextReady()), SLOT(contextReady()));
return;
}
createPulseStream();
}
}
void QSoundEffectPrivate::decoderError()
{
qWarning("QSoundEffect(pulseaudio): Error decoding source");
disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
bool playingDirty = false;
if (m_playing) {
m_playing = false;
playingDirty = true;
}
setStatus(QSoundEffect::Error);
if (playingDirty)
emit playingChanged();
}
void QSoundEffectPrivate::unloadPulseStream()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "unloadPulseStream";
#endif
m_sinkInputId = -1;
PulseDaemonLocker locker;
if (m_pulseStream) {
pa_stream_set_state_callback(m_pulseStream, 0, 0);
pa_stream_set_write_callback(m_pulseStream, 0, 0);
pa_stream_set_underflow_callback(m_pulseStream, 0, 0);
pa_stream_disconnect(m_pulseStream);
pa_stream_unref(m_pulseStream);
disconnect(daemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume()));
m_pulseStream = 0;
}
}
void QSoundEffectPrivate::prepare()
{
if (!m_pulseStream || !m_sampleReady)
return;
PulseDaemonLocker locker;
pa_stream_set_write_callback(m_pulseStream, stream_write_callback, this);
pa_stream_set_underflow_callback(m_pulseStream, stream_underrun_callback, this);
m_stopping = false;
size_t writeBytes = size_t(qMin(m_pulseBufferSize, m_sample->data().size()));
#ifdef QT_PA_DEBUG
qDebug() << this << "prepare(): writable size =" << pa_stream_writable_size(m_pulseStream)
<< "actual writeBytes =" << writeBytes
<< "m_playQueued =" << m_playQueued;
#endif
m_position = int(writeBytes);
if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data())), writeBytes,
stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) {
qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(daemon()->context())));
}
if (m_playQueued) {
m_playQueued = false;
m_runningCount = m_loopCount;
playSample();
}
}
void QSoundEffectPrivate::uploadSample()
{
if (m_runningCount == 0) {
#ifdef QT_PA_DEBUG
qDebug() << this << "uploadSample: return due to 0 m_runningCount";
#endif
return;
}
#ifdef QT_PA_DEBUG
qDebug() << this << "uploadSample: m_runningCount =" << m_runningCount;
#endif
if (m_position == m_sample->data().size()) {
m_position = 0;
if (m_runningCount > 0)
m_runningCount--;
if (m_runningCount == 0) {
return;
}
}
int writtenBytes = 0;
int writableSize = int(pa_stream_writable_size(m_pulseStream));
int firstPartLength = qMin(m_sample->data().size() - m_position, writableSize);
if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data()) + m_position),
firstPartLength, stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) {
qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(daemon()->context())));
}
writtenBytes = firstPartLength;
m_position += firstPartLength;
if (m_position == m_sample->data().size()) {
m_position = 0;
if (m_runningCount > 0)
m_runningCount--;
if (m_runningCount != 0 && firstPartLength < writableSize)
{
while (writtenBytes < writableSize) {
int writeSize = qMin(writableSize - writtenBytes, m_sample->data().size());
if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data())),
writeSize, stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) {
qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(daemon()->context())));
}
writtenBytes += writeSize;
if (writeSize < m_sample->data().size()) {
m_position = writeSize;
break;
}
if (m_runningCount > 0)
m_runningCount--;
if (m_runningCount == 0)
break;
}
}
}
#ifdef QT_PA_DEBUG
qDebug() << this << "uploadSample: use direct write, writeable size =" << writableSize
<< "actual writtenBytes =" << writtenBytes;
#endif
}
void QSoundEffectPrivate::playSample()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "playSample";
#endif
Q_ASSERT(m_pulseStream);
pa_operation_unref(pa_stream_cork(m_pulseStream, 0, 0, 0));
}
void QSoundEffectPrivate::stop()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "stop";
#endif
if (!m_playing)
return;
setPlaying(false);
PulseDaemonLocker locker;
m_stopping = true;
if (m_pulseStream)
emptyStream();
m_runningCount = 0;
m_position = 0;
m_playQueued = false;
}
void QSoundEffectPrivate::underRun()
{
stop();
}
void QSoundEffectPrivate::streamReady()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "streamReady";
#endif
PulseDaemonLocker locker;
m_sinkInputId = pa_stream_get_index(m_pulseStream);
updateMuted();
updateVolume();
#ifdef QT_PA_DEBUG
const pa_buffer_attr *realBufAttr = pa_stream_get_buffer_attr(m_pulseStream);
qDebug() << this << "m_sinkInputId =" << m_sinkInputId
<< "tlength =" << realBufAttr->tlength << "maxlength =" << realBufAttr->maxlength
<< "minreq = " << realBufAttr->minreq << "prebuf =" << realBufAttr->prebuf;
#endif
prepare();
setStatus(QSoundEffect::Ready);
}
void QSoundEffectPrivate::createPulseStream()
{
#ifdef QT_PA_DEBUG
qDebug() << this << "createPulseStream";
#endif
pa_proplist *propList = pa_proplist_new();
pa_proplist_sets(propList, PA_PROP_MEDIA_ROLE, "soundeffect");
pa_stream *stream = pa_stream_new_with_proplist(daemon()->context(), m_name.constData(), &m_pulseSpec, 0, propList);
pa_proplist_free(propList);
connect(daemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume()));
if (stream == 0) {
qWarning("QSoundEffect(pulseaudio): Failed to create stream");
m_pulseStream = 0;
setStatus(QSoundEffect::Error);
setPlaying(false);
return;
}
else {
pa_stream_set_state_callback(stream, stream_state_callback, this);
pa_stream_set_write_callback(stream, stream_write_callback, this);
pa_stream_set_underflow_callback(stream, stream_underrun_callback, this);
}
m_pulseStream = stream;
#ifndef QTM_PULSEAUDIO_DEFAULTBUFFER
pa_buffer_attr bufferAttr;
bufferAttr.tlength = qMin(m_sample->data().size(), QT_PA_STREAM_BUFFER_SIZE_MAX);
bufferAttr.maxlength = -1;
bufferAttr.minreq = bufferAttr.tlength / 2;
bufferAttr.prebuf = -1;
bufferAttr.fragsize = -1;
if (pa_stream_connect_playback(m_pulseStream, 0, &bufferAttr,
#else
if (pa_stream_connect_playback(m_pulseStream, 0, 0,
#endif
m_muted ? pa_stream_flags_t(PA_STREAM_START_MUTED | PA_STREAM_START_CORKED)
: pa_stream_flags_t(PA_STREAM_START_UNMUTED | PA_STREAM_START_CORKED),
0, 0) < 0) {
qWarning("QSoundEffect(pulseaudio): Failed to connect stream, error = %s",
pa_strerror(pa_context_errno(daemon()->context())));
}
}
void QSoundEffectPrivate::contextReady()
{
disconnect(daemon(), SIGNAL(contextReady()), this, SLOT(contextReady()));
PulseDaemonLocker locker;
createPulseStream();
}
void QSoundEffectPrivate::stream_write_callback(pa_stream *s, size_t length, void *userdata)
{
Q_UNUSED(length);
Q_UNUSED(s)
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
#ifdef QT_PA_DEBUG
qDebug() << self << "stream_write_callback";
#endif
self->uploadSample();
}
void QSoundEffectPrivate::stream_state_callback(pa_stream *s, void *userdata)
{
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
switch (pa_stream_get_state(s)) {
case PA_STREAM_READY:
{
#ifdef QT_PA_DEBUG
qDebug() << self << "pulse stream ready";
#endif
const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(self->m_pulseStream);
self->m_pulseBufferSize = bufferAttr->tlength;
if (bufferAttr->prebuf > uint32_t(self->m_sample->data().size())) {
pa_buffer_attr newBufferAttr;
newBufferAttr = *bufferAttr;
newBufferAttr.prebuf = self->m_sample->data().size();
pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, userdata);
} else {
QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection);
}
break;
}
case PA_STREAM_CREATING:
#ifdef QT_PA_DEBUG
qDebug() << self << "pulse stream creating";
#endif
break;
case PA_STREAM_TERMINATED:
#ifdef QT_PA_DEBUG
qDebug() << self << "pulse stream terminated";
#endif
break;
case PA_STREAM_FAILED:
default:
qWarning("QSoundEffect(pulseaudio): Error in pulse audio stream");
break;
}
}
void QSoundEffectPrivate::stream_reset_buffer_callback(pa_stream *s, int success, void *userdata)
{
Q_UNUSED(s);
if (!success)
qWarning("QSoundEffect(pulseaudio): faild to reset buffer attribute");
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
#ifdef QT_PA_DEBUG
qDebug() << self << "stream_reset_buffer_callback";
#endif
const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(self->m_pulseStream);
self->m_pulseBufferSize = bufferAttr->tlength;
if (bufferAttr->prebuf > uint32_t(self->m_sample->data().size())) {
pa_buffer_attr newBufferAttr;
newBufferAttr = *bufferAttr;
newBufferAttr.prebuf = self->m_sample->data().size();
pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, userdata);
} else {
QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection);
}
}
void QSoundEffectPrivate::stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata)
{
Q_UNUSED(s);
if (!success)
qWarning("QSoundEffect(pulseaudio): faild to adjust pre-buffer attribute");
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
#ifdef QT_PA_DEBUG
qDebug() << self << "stream_adjust_prebuffer_callback";
#endif
QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection);
}
void QSoundEffectPrivate::setvolume_callback(pa_context *c, int success, void *userdata)
{
Q_UNUSED(c);
Q_UNUSED(userdata);
#ifdef QT_PA_DEBUG
qDebug() << reinterpret_cast<QSoundEffectPrivate*>(userdata) << "setvolume_callback";
#endif
if (!success) {
qWarning("QSoundEffect(pulseaudio): faild to set volume");
}
}
void QSoundEffectPrivate::setmuted_callback(pa_context *c, int success, void *userdata)
{
Q_UNUSED(c);
Q_UNUSED(userdata);
#ifdef QT_PA_DEBUG
qDebug() << reinterpret_cast<QSoundEffectPrivate*>(userdata) << "setmuted_callback";
#endif
if (!success) {
qWarning("QSoundEffect(pulseaudio): faild to set muted");
}
}
void QSoundEffectPrivate::stream_underrun_callback(pa_stream *s, void *userdata)
{
Q_UNUSED(s);
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
#ifdef QT_PA_DEBUG
qDebug() << self << "stream_underrun_callback";
#endif
if (self->m_runningCount == 0 && !self->m_playQueued)
QMetaObject::invokeMethod(self, "underRun", Qt::QueuedConnection);
#ifdef QT_PA_DEBUG
else
qDebug() << "underun corked =" << pa_stream_is_corked(s);
#endif
}
void QSoundEffectPrivate::stream_cork_callback(pa_stream *s, int success, void *userdata)
{
Q_UNUSED(s);
if (!success)
qWarning("QSoundEffect(pulseaudio): faild to stop");
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
#ifdef QT_PA_DEBUG
qDebug() << self << "stream_cork_callback";
#endif
QMetaObject::invokeMethod(self, "prepare", Qt::QueuedConnection);
}
void QSoundEffectPrivate::stream_flush_callback(pa_stream *s, int success, void *userdata)
{
Q_UNUSED(s);
if (!success)
qWarning("QSoundEffect(pulseaudio): faild to drain");
QSoundEffectPrivate *self = reinterpret_cast<QSoundEffectPrivate*>(userdata);
#ifdef QT_PA_DEBUG
qDebug() << self << "stream_flush_callback";
#endif
QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection);
}
void QSoundEffectPrivate::stream_write_done_callback(void *p)
{
Q_UNUSED(p);
#ifdef QT_PA_DEBUG
qDebug() << "stream_write_done_callback";
#endif
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_pulse_p.cpp"
#include "qsoundeffect_pulse_p.moc"

View File

@@ -0,0 +1,163 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_PULSE_H
#define QSOUNDEFFECT_PULSE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsoundeffect_p.h"
#include <QtCore/qobject.h>
#include <QtCore/qdatetime.h>
#include <qmediaplayer.h>
#include <pulse/pulseaudio.h>
#include "qsamplecache_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QSoundEffectPrivate : public QObject
{
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying() const;
QSoundEffect::Status status() const;
public Q_SLOTS:
void play();
void stop();
Q_SIGNALS:
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
private Q_SLOTS:
void decoderError();
void sampleReady();
void uploadSample();
void contextReady();
void underRun();
void prepare();
void streamReady();
void emptyComplete();
void updateVolume();
void updateMuted();
private:
void playSample();
void emptyStream();
void createPulseStream();
void unloadPulseStream();
void setPlaying(bool playing);
void setStatus(QSoundEffect::Status status);
static void stream_write_callback(pa_stream *s, size_t length, void *userdata);
static void stream_state_callback(pa_stream *s, void *userdata);
static void stream_underrun_callback(pa_stream *s, void *userdata);
static void stream_cork_callback(pa_stream *s, int success, void *userdata);
static void stream_flush_callback(pa_stream *s, int success, void *userdata);
static void stream_write_done_callback(void *p);
static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata);
static void stream_reset_buffer_callback(pa_stream *s, int success, void *userdata);
static void setvolume_callback(pa_context *c, int success, void *userdata);
static void setmuted_callback(pa_context *c, int success, void *userdata);
pa_stream *m_pulseStream;
int m_sinkInputId;
pa_sample_spec m_pulseSpec;
int m_pulseBufferSize;
bool m_emptying;
bool m_sampleReady;
bool m_playing;
QSoundEffect::Status m_status;
bool m_muted;
bool m_playQueued;
bool m_stopping;
int m_volume;
int m_loopCount;
int m_runningCount;
QUrl m_source;
QByteArray m_name;
QSample *m_sample;
int m_position;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_PULSE_H

View File

@@ -0,0 +1,233 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qsoundeffect_qmedia_p.h"
#include <QtCore/qcoreapplication.h>
#include "qmediacontent.h"
#include "qmediaplayer.h"
QT_BEGIN_NAMESPACE
QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
QObject(parent),
m_loopCount(1),
m_runningCount(0),
m_player(0),
m_status(QSoundEffect::Null),
m_playing(false)
{
m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency);
connect(m_player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(stateChanged(QMediaPlayer::State)));
connect(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
connect(m_player, SIGNAL(error(QMediaPlayer::Error)), SLOT(error(QMediaPlayer::Error)));
connect(m_player, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged()));
connect(m_player, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged()));
}
QSoundEffectPrivate::~QSoundEffectPrivate()
{
}
QStringList QSoundEffectPrivate::supportedMimeTypes()
{
return QMediaPlayer::supportedMimeTypes();
}
QUrl QSoundEffectPrivate::source() const
{
return m_player->media().canonicalUrl();
}
void QSoundEffectPrivate::setSource(const QUrl &url)
{
m_player->setMedia(url);
}
int QSoundEffectPrivate::loopCount() const
{
return m_loopCount;
}
void QSoundEffectPrivate::setLoopCount(int loopCount)
{
m_loopCount = loopCount;
}
int QSoundEffectPrivate::volume() const
{
return m_player->volume();
}
void QSoundEffectPrivate::setVolume(int volume)
{
m_player->setVolume(volume);
}
bool QSoundEffectPrivate::isMuted() const
{
return m_player->isMuted();
}
void QSoundEffectPrivate::setMuted(bool muted)
{
m_player->setMuted(muted);
}
bool QSoundEffectPrivate::isLoaded() const
{
return m_status == QSoundEffect::Ready;
}
bool QSoundEffectPrivate::isPlaying() const
{
return m_playing;
}
QSoundEffect::Status QSoundEffectPrivate::status() const
{
return m_status;
}
void QSoundEffectPrivate::play()
{
if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error)
return;
if (m_loopCount < 0) {
m_runningCount = -1;
}
else {
if (m_runningCount < 0)
m_runningCount = 0;
m_runningCount += m_loopCount;
}
m_player->play();
}
void QSoundEffectPrivate::stop()
{
m_runningCount = 0;
m_player->stop();
}
void QSoundEffectPrivate::stateChanged(QMediaPlayer::State state)
{
if (state == QMediaPlayer::StoppedState) {
if (m_runningCount < 0) {
m_player->play();
} else if (m_runningCount == 0) {
setPlaying(false);
return;
} else if (--m_runningCount > 0) {
m_player->play();
} else {
setPlaying(false);
}
} else {
setPlaying(true);
}
}
void QSoundEffectPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
switch(status) {
case QMediaPlayer::LoadingMedia:
setStatus(QSoundEffect::Loading);
break;
case QMediaPlayer::NoMedia:
setStatus(QSoundEffect::Null);
break;
case QMediaPlayer::InvalidMedia:
setStatus(QSoundEffect::Error);
break;
default:
setStatus(QSoundEffect::Ready);
break;
}
}
void QSoundEffectPrivate::error(QMediaPlayer::Error err)
{
bool playingDirty = false;
if (m_playing) {
m_playing = false;
playingDirty = true;
}
setStatus(QSoundEffect::Error);
if (playingDirty)
emit playingChanged();
}
void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
{
if (m_status == status)
return;
bool oldLoaded = isLoaded();
m_status = status;
emit statusChanged();
if (oldLoaded != isLoaded())
emit loadedChanged();
}
void QSoundEffectPrivate::setPlaying(bool playing)
{
if (m_playing == playing)
return;
m_playing = playing;
emit playingChanged();
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_qmedia_p.cpp"

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_QMEDIA_H
#define QSOUNDEFFECT_QMEDIA_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include "qmediaplayer.h"
#include "qsoundeffect_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QSoundEffectPrivate : public QObject
{
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying() const;
QSoundEffect::Status status() const;
public Q_SLOTS:
void play();
void stop();
Q_SIGNALS:
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
private Q_SLOTS:
void stateChanged(QMediaPlayer::State);
void mediaStatusChanged(QMediaPlayer::MediaStatus);
void error(QMediaPlayer::Error);
private:
void setStatus(QSoundEffect::Status status);
void setPlaying(bool playing);
int m_loopCount;
int m_runningCount;
bool m_playing;
QSoundEffect::Status m_status;
QMediaPlayer *m_player;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_QMEDIA_H

View File

@@ -0,0 +1,222 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qsoundeffect_qsound_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtWidgets/qsound.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
QObject(parent),
m_playing(false),
m_timerID(0),
m_muted(false),
m_loopCount(1),
m_volume(100),
m_status(QSoundEffect::Null),
m_sound(0)
{
if (!QSound::isAvailable())
qWarning("SoundEffect(qsound) : not available");
}
QSoundEffectPrivate::~QSoundEffectPrivate()
{
}
QStringList QSoundEffectPrivate::supportedMimeTypes()
{
QStringList supportedTypes;
supportedTypes << QLatin1String("audio/x-wav") << QLatin1String("audio/vnd.wave") ;
return supportedTypes;
}
QUrl QSoundEffectPrivate::source() const
{
return m_source;
}
void QSoundEffectPrivate::setSource(const QUrl &url)
{
if (url.isEmpty()) {
m_source = QUrl();
setStatus(QSoundEffect::Null);
return;
}
if (url.scheme() != QLatin1String("file")) {
m_source = url;
setStatus(QSoundEffect::Error);
return;
}
if (m_sound != 0)
delete m_sound;
m_source = url;
m_sound = new QSound(m_source.toLocalFile(), this);
m_sound->setLoops(m_loopCount);
m_status = QSoundEffect::Ready;
emit statusChanged();
emit loadedChanged();
}
int QSoundEffectPrivate::loopCount() const
{
return m_loopCount;
}
void QSoundEffectPrivate::setLoopCount(int lc)
{
m_loopCount = lc;
if (m_sound)
m_sound->setLoops(lc);
}
int QSoundEffectPrivate::volume() const
{
return m_volume;
}
void QSoundEffectPrivate::setVolume(int v)
{
m_volume = v;
}
bool QSoundEffectPrivate::isMuted() const
{
return m_muted;
}
void QSoundEffectPrivate::setMuted(bool muted)
{
m_muted = muted;
}
bool QSoundEffectPrivate::isLoaded() const
{
return m_status == QSoundEffect::Ready;
}
void QSoundEffectPrivate::play()
{
if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error)
return;
if (m_timerID != 0)
killTimer(m_timerID);
m_timerID = startTimer(500);
m_sound->play();
setPlaying(true);
}
void QSoundEffectPrivate::stop()
{
if (m_timerID != 0)
killTimer(m_timerID);
m_timerID = 0;
m_sound->stop();
setPlaying(false);
}
bool QSoundEffectPrivate::isPlaying()
{
if (m_playing && m_sound && m_sound->isFinished()) {
if (m_timerID != 0)
killTimer(m_timerID);
m_timerID = 0;
setPlaying(false);
}
return m_playing;
}
QSoundEffect::Status QSoundEffectPrivate::status() const
{
return m_status;
}
void QSoundEffectPrivate::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event);
setPlaying(!m_sound->isFinished());
if (isPlaying())
return;
killTimer(m_timerID);
m_timerID = 0;
}
void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
{
if (m_status == status)
return;
bool oldLoaded = isLoaded();
m_status = status;
emit statusChanged();
if (oldLoaded != isLoaded())
emit loadedChanged();
}
void QSoundEffectPrivate::setPlaying(bool playing)
{
if (m_playing == playing)
return;
m_playing = playing;
emit playingChanged();
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_qsound_p.cpp"

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_QSOUND_H
#define QSOUNDEFFECT_QSOUND_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include "qsoundeffect_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QSound;
class QSoundEffectPrivate : public QObject
{
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying();
QSoundEffect::Status status() const;
public Q_SLOTS:
void play();
void stop();
Q_SIGNALS:
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
private:
void setStatus(QSoundEffect::Status status);
void setPlaying(bool playing);
void timerEvent(QTimerEvent *event);
bool m_playing;
int m_timerID;
bool m_muted;
int m_loopCount;
int m_volume;
QSoundEffect::Status m_status;
QSound *m_sound;
QUrl m_source;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_QSOUND_H

View File

@@ -0,0 +1,232 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qwavedecoder_p.h"
#include <QtCore/qtimer.h>
#include <QtCore/qendian.h>
QT_BEGIN_NAMESPACE
QWaveDecoder::QWaveDecoder(QIODevice *s, QObject *parent):
QIODevice(parent),
haveFormat(false),
dataSize(0),
remaining(0),
source(s),
state(QWaveDecoder::InitialState)
{
open(QIODevice::ReadOnly | QIODevice::Unbuffered);
if (enoughDataAvailable())
QTimer::singleShot(0, this, SLOT(handleData()));
else
connect(source, SIGNAL(readyRead()), SLOT(handleData()));
}
QWaveDecoder::~QWaveDecoder()
{
}
QAudioFormat QWaveDecoder::audioFormat() const
{
return format;
}
int QWaveDecoder::duration() const
{
return size() * 1000 / (format.sampleSize() / 8) / format.channels() / format.frequency();
}
qint64 QWaveDecoder::size() const
{
return haveFormat ? dataSize : 0;
}
bool QWaveDecoder::isSequential() const
{
return source->isSequential();
}
qint64 QWaveDecoder::bytesAvailable() const
{
return haveFormat ? source->bytesAvailable() : 0;
}
qint64 QWaveDecoder::readData(char *data, qint64 maxlen)
{
return haveFormat ? source->read(data, maxlen) : 0;
}
qint64 QWaveDecoder::writeData(const char *data, qint64 len)
{
Q_UNUSED(data);
Q_UNUSED(len);
return -1;
}
void QWaveDecoder::handleData()
{
if (state == QWaveDecoder::InitialState) {
if (source->bytesAvailable() < qint64(sizeof(RIFFHeader)))
return;
RIFFHeader riff;
source->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader));
if (qstrncmp(riff.descriptor.id, "RIFF", 4) != 0 ||
qstrncmp(riff.type, "WAVE", 4) != 0) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
emit invalidFormat();
return;
} else {
state = QWaveDecoder::WaitingForFormatState;
}
}
if (state == QWaveDecoder::WaitingForFormatState) {
if (findChunk("fmt ")) {
chunk descriptor;
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (source->bytesAvailable() < qint64(descriptor.size + sizeof(chunk)))
return;
WAVEHeader wave;
source->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader));
if (descriptor.size > sizeof(WAVEHeader))
discardBytes(descriptor.size - sizeof(WAVEHeader));
if (wave.audioFormat != 0 && wave.audioFormat != 1) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
emit invalidFormat();
return;
} else {
int bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
format.setCodec(QLatin1String("audio/pcm"));
format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setFrequency(qFromLittleEndian<quint32>(wave.sampleRate));
format.setSampleSize(bps);
format.setChannels(qFromLittleEndian<quint16>(wave.numChannels));
state = QWaveDecoder::WaitingForDataState;
}
}
}
if (state == QWaveDecoder::WaitingForDataState) {
if (findChunk("data")) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
chunk descriptor;
source->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
dataSize = descriptor.size;
haveFormat = true;
connect(source, SIGNAL(readyRead()), SIGNAL(readyRead()));
emit formatKnown();
return;
}
}
if (source->atEnd()) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
emit invalidFormat();
return;
}
}
bool QWaveDecoder::enoughDataAvailable()
{
if (source->bytesAvailable() < qint64(sizeof(chunk)))
return false;
chunk descriptor;
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (source->bytesAvailable() < qint64(sizeof(chunk) + descriptor.size))
return false;
return true;
}
bool QWaveDecoder::findChunk(const char *chunkId)
{
if (source->bytesAvailable() < qint64(sizeof(chunk)))
return false;
chunk descriptor;
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (qstrncmp(descriptor.id, chunkId, 4) == 0)
return true;
while (source->bytesAvailable() >= qint64(sizeof(chunk) + descriptor.size)) {
discardBytes(sizeof(chunk) + descriptor.size);
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (qstrncmp(descriptor.id, chunkId, 4) == 0)
return true;
}
return false;
}
void QWaveDecoder::discardBytes(qint64 numBytes)
{
if (source->isSequential())
source->read(numBytes);
else
source->seek(source->pos() + numBytes);
}
QT_END_NAMESPACE
#include "moc_qwavedecoder_p.cpp"

View File

@@ -0,0 +1,137 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef WAVEDECODER_H
#define WAVEDECODER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qiodevice.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QWaveDecoder : public QIODevice
{
Q_OBJECT
public:
explicit QWaveDecoder(QIODevice *source, QObject *parent = 0);
~QWaveDecoder();
QAudioFormat audioFormat() const;
int duration() const;
qint64 size() const;
bool isSequential() const;
qint64 bytesAvailable() const;
Q_SIGNALS:
void formatKnown();
void invalidFormat();
private Q_SLOTS:
void handleData();
private:
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
bool enoughDataAvailable();
bool findChunk(const char *chunkId);
void discardBytes(qint64 numBytes);
enum State {
InitialState,
WaitingForFormatState,
WaitingForDataState
};
struct chunk
{
char id[4];
quint32 size;
};
struct RIFFHeader
{
chunk descriptor;
char type[4];
};
struct WAVEHeader
{
chunk descriptor;
quint16 audioFormat;
quint16 numChannels;
quint32 sampleRate;
quint32 byteRate;
quint16 blockAlign;
quint16 bitsPerSample;
};
bool haveFormat;
qint64 dataSize;
qint64 remaining;
QAudioFormat format;
QIODevice *source;
State state;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // WAVEDECODER_H

View File

@@ -0,0 +1,156 @@
load(qt_module)
TARGET = QtMultimedia
QPRO_PWD = $$PWD
QT = core network gui
CONFIG += module
MODULE_PRI += ../../modules/qt_multimedia.pri
contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2) {
} else {
DEFINES += QT_NO_OPENGL
}
!static:DEFINES += QT_MAKEDLL
DEFINES += QT_BUILD_MULTIMEDIA_LIB
load(qt_module_config)
HEADERS += qtmultimediaversion.h
PRIVATE_HEADERS += \
qmediacontrol_p.h \
qmediaobject_p.h \
qmediaservice_p.h \
qmediaplaylist_p.h \
qmediaplaylistprovider_p.h \
qmediaimageviewerservice_p.h \
qmediapluginloader_p.h \
qvideosurfaceoutput_p.h
PUBLIC_HEADERS += \
qmediacontrol.h \
qmediaobject.h \
qmediaservice.h \
qmediabindableinterface.h \
qlocalmediaplaylistprovider.h \
qmediaimageviewer.h \
qmediaplayer.h \
qmediaplayercontrol.h \
qmediaplaylist.h \
qmediaplaylistnavigator.h \
qmediaplaylistprovider.h \
qmediaplaylistioplugin.h \
qmediabackgroundplaybackcontrol.h \
qmediacontent.h \
qmediaresource.h \
qmediarecorder.h \
qmediaencodersettings.h \
qmediarecordercontrol.h \
qmediaserviceprovider.h \
qmediaserviceproviderplugin.h \
qmetadatareadercontrol.h \
qmetadatawritercontrol.h \
qmediastreamscontrol.h \
qradiotuner.h \
qradiotunercontrol.h \
qtmedianamespace.h \
qaudioencodercontrol.h \
qvideoencodercontrol.h \
qimageencodercontrol.h \
qaudiocapturesource.h \
qmediacontainercontrol.h \
qmediaplaylistcontrol.h \
qmediaplaylistsourcecontrol.h \
qaudioendpointselector.h \
qvideodevicecontrol.h \
qvideorenderercontrol.h \
qmediatimerange.h \
qmedianetworkaccesscontrol.h \
qmediaenumdebug.h \
qtmultimediadefs.h
SOURCES += qmediacontrol.cpp \
qmediaobject.cpp \
qmediaservice.cpp \
qmediabindableinterface.cpp \
qlocalmediaplaylistprovider.cpp \
qmediaimageviewer.cpp \
qmediaimageviewerservice.cpp \
qmediaplayer.cpp \
qmediaplayercontrol.cpp \
qmediaplaylist.cpp \
qmediaplaylistioplugin.cpp \
qmediaplaylistnavigator.cpp \
qmediaplaylistprovider.cpp \
qmediarecorder.cpp \
qmediaencodersettings.cpp \
qmediarecordercontrol.cpp \
qmediacontent.cpp \
qmediaresource.cpp \
qmediaserviceprovider.cpp \
qmetadatareadercontrol.cpp \
qmetadatawritercontrol.cpp \
qmediastreamscontrol.cpp \
qradiotuner.cpp \
qradiotunercontrol.cpp \
qaudioencodercontrol.cpp \
qvideoencodercontrol.cpp \
qimageencodercontrol.cpp \
qaudiocapturesource.cpp \
qmediacontainercontrol.cpp \
qmediaplaylistcontrol.cpp \
qmediaplaylistsourcecontrol.cpp \
qaudioendpointselector.cpp \
qvideodevicecontrol.cpp \
qmediapluginloader.cpp \
qvideorenderercontrol.cpp \
qmediatimerange.cpp \
qmedianetworkaccesscontrol.cpp \
qvideosurfaceoutput.cpp \
qmediabackgroundplaybackcontrol.cpp
#Camera
PUBLIC_HEADERS += \
qcamera.h \
qcameraimagecapture.h \
qcameraimagecapturecontrol.h \
qcameraexposure.h \
qcamerafocus.h \
qcameraimageprocessing.h \
qcameracontrol.h \
qcameralockscontrol.h \
qcameraexposurecontrol.h \
qcamerafocuscontrol.h \
qcameraflashcontrol.h \
qcameraimageprocessingcontrol.h \
qcameracapturedestinationcontrol.h \
qcameracapturebufferformatcontrol.h
SOURCES += \
qcamera.cpp \
qcameraexposure.cpp \
qcamerafocus.cpp \
qcameraimageprocessing.cpp \
qcameraimagecapture.cpp \
qcameraimagecapturecontrol.cpp \
qcameracontrol.cpp \
qcameralockscontrol.cpp \
qcameraexposurecontrol.cpp \
qcamerafocuscontrol.cpp \
qcameraflashcontrol.cpp \
qcameraimageprocessingcontrol.cpp \
qcameracapturedestinationcontrol.cpp \
qcameracapturebufferformatcontrol.cpp
include(audio/audio.pri)
include(video/video.pri)
include(effects/effects.pri)
mac:!qpa {
LIBS += -framework AppKit -framework QuartzCore -framework QTKit
}
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS

View File

@@ -0,0 +1,275 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qmediaobject_p.h"
#include <qaudiocapturesource.h>
#include "qaudioendpointselector.h"
QT_BEGIN_NAMESPACE
/*!
\class QAudioCaptureSource
\brief The QAudioCaptureSource class provides an interface to query and select an audio input endpoint.
\inmodule QtMultimedia
\ingroup multimedia
\since 1.0
QAudioCaptureSource provides access to the audio inputs available on your system.
You can query these inputs and select one to use.
A typical implementation example:
\snippet doc/src/snippets/multimedia-snippets/media.cpp Audio capture source
The audiocapturesource interface is then used to:
- Get and Set the audio input to use.
The capture interface is then used to:
- Set the destination using setOutputLocation()
- Set the format parameters using setAudioCodec(),
- Control the recording using record(),stop()
\sa QMediaRecorder
*/
class QAudioCaptureSourcePrivate : public QMediaObjectPrivate
{
public:
Q_DECLARE_PUBLIC(QAudioCaptureSource)
void initControls()
{
Q_Q(QAudioCaptureSource);
if (service != 0)
audioEndpointSelector = qobject_cast<QAudioEndpointSelector*>(service->requestControl(QAudioEndpointSelector_iid));
if (audioEndpointSelector) {
q->connect(audioEndpointSelector, SIGNAL(activeEndpointChanged(const QString&)),
SIGNAL(activeAudioInputChanged(const QString&)));
q->connect(audioEndpointSelector, SIGNAL(availableEndpointsChanged()),
SIGNAL(availableAudioInputsChanged()));
q->connect(audioEndpointSelector, SIGNAL(availableEndpointsChanged()),
SLOT(statusChanged()));
errorState = QtMultimedia::NoError;
}
}
QAudioCaptureSourcePrivate():provider(0), audioEndpointSelector(0), errorState(QtMultimedia::ServiceMissingError) {}
QMediaServiceProvider *provider;
QAudioEndpointSelector *audioEndpointSelector;
QtMultimedia::AvailabilityError errorState;
};
/*!
Construct a QAudioCaptureSource using the QMediaService from \a provider, with \a parent.
\since 1.0
*/
QAudioCaptureSource::QAudioCaptureSource(QObject *parent, QMediaServiceProvider *provider):
QMediaObject(*new QAudioCaptureSourcePrivate, parent, provider->requestService(Q_MEDIASERVICE_AUDIOSOURCE))
{
Q_D(QAudioCaptureSource);
d->provider = provider;
d->initControls();
}
/*!
Destroys the audiocapturesource object.
*/
QAudioCaptureSource::~QAudioCaptureSource()
{
Q_D(QAudioCaptureSource);
if (d->service && d->audioEndpointSelector)
d->service->releaseControl(d->audioEndpointSelector);
if (d->provider)
d->provider->releaseService(d->service);
}
/*!
Returns the error state of the audio capture service.
\since 1.0
*/
QtMultimedia::AvailabilityError QAudioCaptureSource::availabilityError() const
{
Q_D(const QAudioCaptureSource);
return d->errorState;
}
/*!
Returns true if the audio capture service is available, otherwise returns false.
\since 1.0
*/
bool QAudioCaptureSource::isAvailable() const
{
Q_D(const QAudioCaptureSource);
if (d->service != NULL) {
if (d->audioEndpointSelector && d->audioEndpointSelector->availableEndpoints().size() > 0)
return true;
}
return false;
}
/*!
Returns a list of available audio inputs
\since 1.0
*/
QList<QString> QAudioCaptureSource::audioInputs() const
{
Q_D(const QAudioCaptureSource);
QList<QString> list;
if (d && d->audioEndpointSelector)
list <<d->audioEndpointSelector->availableEndpoints();
return list;
}
/*!
Returns the description of the audio input device with \a name.
\since 1.0
*/
QString QAudioCaptureSource::audioDescription(const QString& name) const
{
Q_D(const QAudioCaptureSource);
if(d->audioEndpointSelector)
return d->audioEndpointSelector->endpointDescription(name);
else
return QString();
}
/*!
Returns the default audio input name.
\since 1.0
*/
QString QAudioCaptureSource::defaultAudioInput() const
{
Q_D(const QAudioCaptureSource);
if(d->audioEndpointSelector)
return d->audioEndpointSelector->defaultEndpoint();
else
return QString();
}
/*!
Returns the active audio input name.
\since 1.0
*/
QString QAudioCaptureSource::activeAudioInput() const
{
Q_D(const QAudioCaptureSource);
if(d->audioEndpointSelector)
return d->audioEndpointSelector->activeEndpoint();
else
return QString();
}
/*!
Set the active audio input to \a name.
\since 1.0
*/
void QAudioCaptureSource::setAudioInput(const QString& name)
{
Q_D(const QAudioCaptureSource);
if(d->audioEndpointSelector)
return d->audioEndpointSelector->setActiveEndpoint(name);
}
/*!
\fn QAudioCaptureSource::activeAudioInputChanged(const QString& name)
Signal emitted when active audio input changes to \a name.
\since 1.0
*/
/*!
\fn QAudioCaptureSource::availableAudioInputsChanged()
Signal is emitted when the available audio inputs change.
\since 1.0
*/
/*!
\internal
\since 1.0
*/
void QAudioCaptureSource::statusChanged()
{
Q_D(QAudioCaptureSource);
if (d->audioEndpointSelector) {
if (d->audioEndpointSelector->availableEndpoints().size() > 0) {
d->errorState = QtMultimedia::NoError;
emit availabilityChanged(true);
} else {
d->errorState = QtMultimedia::BusyError;
emit availabilityChanged(false);
}
} else {
d->errorState = QtMultimedia::ServiceMissingError;
emit availabilityChanged(false);
}
}
#include "moc_qaudiocapturesource.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOCAPTURESOURCE_H
#define QAUDIOCAPTURESOURCE_H
#include <QtCore/qstringlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qsize.h>
#include <qaudioformat.h>
#include "qmediarecorder.h"
#include "qmediacontrol.h"
#include "qmediaobject.h"
#include "qmediaservice.h"
#include "qmediaserviceprovider.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAudioCaptureSourcePrivate;
class Q_MULTIMEDIA_EXPORT QAudioCaptureSource : public QMediaObject
{
Q_OBJECT
public:
QAudioCaptureSource(QObject *parent = 0, QMediaServiceProvider *service = QMediaServiceProvider::defaultServiceProvider());
~QAudioCaptureSource();
bool isAvailable() const;
QtMultimedia::AvailabilityError availabilityError() const;
QList<QString> audioInputs() const;
QString audioDescription(const QString& name) const;
QString defaultAudioInput() const;
QString activeAudioInput() const;
public Q_SLOTS:
void setAudioInput(const QString& name);
Q_SIGNALS:
void activeAudioInputChanged(const QString& name);
void availableAudioInputsChanged();
private Q_SLOTS:
void statusChanged();
private:
Q_DECLARE_PRIVATE(QAudioCaptureSource)
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOCAPTURESOURCE_H

View File

@@ -0,0 +1,167 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudioencodercontrol.h"
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
/*!
\class QAudioEncoderControl
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.0
\brief The QAudioEncoderControl class provides access to the settings of a
media service that performs audio encoding.
If a QMediaService supports encoding audio data it will implement
QAudioEncoderControl. This control provides information about the limits
of restricted audio encoder options and allows the selection of a set of
audio encoder settings as specified in a QAudioEncoderSettings object.
The functionality provided by this control is exposed to application code through the
QMediaRecorder class.
The interface name of QAudioEncoderControl is \c com.nokia.Qt.QAudioEncoderControl/1.0 as
defined in QAudioEncoderControl_iid.
\sa QMediaService::requestControl(), QMediaRecorder
*/
/*!
\macro QAudioEncoderControl_iid
\c com.nokia.Qt.AudioEncoderControl/1.0
Defines the interface name of the QAudioEncoderControl class.
\relates QAudioEncoderControl
*/
/*!
Create a new audio encode control object with the given \a parent.
*/
QAudioEncoderControl::QAudioEncoderControl(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys the audio encode control.
*/
QAudioEncoderControl::~QAudioEncoderControl()
{
}
/*!
\fn QAudioEncoderControl::supportedAudioCodecs() const
Returns the list of supported audio codec names.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::codecDescription(const QString &codec) const
Returns description of audio \a codec.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
bool *continuous) const
Returns the list of supported audio sample rates, if known.
If non null audio \a settings parameter is passed,
the returned list is reduced to sample rates supported with partial settings applied.
It can be used for example to query the list of sample rates, supported by specific audio codec.
If the encoder supports arbitrary sample rates within the supported rates range,
*\a continuous is set to true, otherwise *\a continuous is set to false.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::supportedEncodingOptions(const QString &codec) const
Returns the list of \a codec specific audio encoding options.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::encodingOption(const QString &codec, const QString &option) const
Returns the value of audio encoding \a option for \a codec.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::setEncodingOption(const QString &codec, const QString &option, const QVariant &value)
Set the \a codec specific \a option to \a value.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::audioSettings() const
Returns the audio encoder settings.
The returned value may be different tha passed to QAudioEncoderControl::setAudioSettings()
if the settings contains the default or undefined parameters.
In this case if the undefined parameters are already resolved, they should be returned.
\since 1.0
*/
/*!
\fn QAudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
Sets the selected audio \a settings.
\since 1.0
*/
#include "moc_qaudioencodercontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOENCODERCONTROL_H
#define QAUDIOENCODERCONTROL_H
#include "qmediacontrol.h"
#include "qmediarecorder.h"
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QStringList;
class QAudioFormat;
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
class Q_MULTIMEDIA_EXPORT QAudioEncoderControl : public QMediaControl
{
Q_OBJECT
public:
virtual ~QAudioEncoderControl();
virtual QStringList supportedAudioCodecs() const = 0;
virtual QString codecDescription(const QString &codecName) const = 0;
virtual QList<int> supportedSampleRates(const QAudioEncoderSettings &settings,
bool *continuous = 0) const = 0;
virtual QAudioEncoderSettings audioSettings() const = 0;
virtual void setAudioSettings(const QAudioEncoderSettings&) = 0;
virtual QStringList supportedEncodingOptions(const QString &codec) const = 0;
virtual QVariant encodingOption(const QString &codec, const QString &name) const = 0;
virtual void setEncodingOption(
const QString &codec, const QString &name, const QVariant &value) = 0;
protected:
QAudioEncoderControl(QObject *parent = 0);
};
#define QAudioEncoderControl_iid "com.nokia.Qt.QAudioEncoderControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QAudioEncoderControl, QAudioEncoderControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOCAPTUREPROPERTIESCONTROL_H

View File

@@ -0,0 +1,140 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qaudioendpointselector.h"
QT_BEGIN_NAMESPACE
/*!
\class QAudioEndpointSelector
\brief The QAudioEndpointSelector class provides an audio endpoint selector media control.
\inmodule QtMultimedia
\ingroup multimedia
\since 1.0
The QAudioEndpointSelector class provides descriptions of the audio
endpoints available on a system and allows one to be selected as the audio
of a media service.
The interface name of QAudioEndpointSelector is \c com.nokia.Qt.QAudioEndpointSelector/1.0 as
defined in QAudioEndpointSelector_iid.
\sa QMediaService::requestControl()
*/
/*!
\macro QAudioEndpointSelector_iid
\c com.nokia.Qt.QAudioEndpointSelector/1.0
Defines the interface name of the QAudioEndpointSelector class.
\relates QAudioEndpointSelector
*/
/*!
Constructs a new audio endpoint selector with the given \a parent.
*/
QAudioEndpointSelector::QAudioEndpointSelector(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys an audio endpoint selector.
*/
QAudioEndpointSelector::~QAudioEndpointSelector()
{
}
/*!
\fn QList<QString> QAudioEndpointSelector::availableEndpoints() const
Returns a list of the names of the available audio endpoints.
\since 1.0
*/
/*!
\fn QString QAudioEndpointSelector::endpointDescription(const QString& name) const
Returns the description of the endpoint \a name.
\since 1.0
*/
/*!
\fn QString QAudioEndpointSelector::defaultEndpoint() const
Returns the name of the default audio endpoint.
\since 1.0
*/
/*!
\fn QString QAudioEndpointSelector::activeEndpoint() const
Returns the name of the currently selected audio endpoint.
\since 1.0
*/
/*!
\fn QAudioEndpointSelector::setActiveEndpoint(const QString& name)
Set the active audio endpoint to \a name.
\since 1.0
*/
/*!
\fn QAudioEndpointSelector::activeEndpointChanged(const QString& name)
Signals that the audio endpoint has changed to \a name.
\since 1.0
*/
/*!
\fn QAudioEndpointSelector::availableEndpointsChanged()
Signals that list of available endpoints has changed.
\since 1.0
*/
#include "moc_qaudioendpointselector.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QAUDIOENDPOINTSELECTOR_H
#define QAUDIOENDPOINTSELECTOR_H
#include <qaudio.h>
#include <qmediacontrol.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QAudioEndpointSelector : public QMediaControl
{
Q_OBJECT
public:
virtual ~QAudioEndpointSelector();
virtual QList<QString> availableEndpoints() const = 0;
virtual QString endpointDescription(const QString& name) const = 0;
virtual QString defaultEndpoint() const = 0;
virtual QString activeEndpoint() const = 0;
public Q_SLOTS:
virtual void setActiveEndpoint(const QString& name) = 0;
Q_SIGNALS:
void activeEndpointChanged(const QString& name);
void availableEndpointsChanged();
protected:
QAudioEndpointSelector(QObject *parent = 0);
};
#define QAudioEndpointSelector_iid "com.nokia.Qt.QAudioEndpointSelector/1.0"
Q_MEDIA_DECLARE_CONTROL(QAudioEndpointSelector, QAudioEndpointSelector_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOENDPOINTSELECTOR_H

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.
**
** 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$
**
****************************************************************************/
/*!
\namespace QAudio
\brief The QAudio namespace contains enums used by the audio classes.
\inmodule QtMultimedia
\ingroup multimedia
*/
/*
\enum QAudio::Error
Error states
\value NoError No errors have occurred
\value OpenError An error opening the audio device
\value IOError An error occurred during read/write of audio device
\value UnderrunError Audio data is not being fed to the audio device at a fast enough rate
\value FatalError A non-recoverable error has occurred, the audio device is not usable at this time.
*/
/*
\enum QAudio::State
Audio processing states
\value ActiveState Audio data is being processed, this state is set after start() is called
and while audio data is available to be processed.
\value SuspendedState The audio device is in a suspended state, this state will only be entered
after suspend() is called.
\value StoppedState The audio device is closed, not processing any audio data
\value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state
is set after start() is called and while no audio data is available to be processed.
*/
/*
\enum QAudio::Mode
Audio I/O modes
\value AudioOutput audio output device
\value AudioInput audio input device
*/

1035
src/multimedia/qcamera.cpp Normal file

File diff suppressed because it is too large Load Diff

238
src/multimedia/qcamera.h Normal file
View File

@@ -0,0 +1,238 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERA_H
#define QCAMERA_H
#include <QtCore/qstringlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qsize.h>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qmediaservice.h>
#include <qcameraexposure.h>
#include <qcamerafocus.h>
#include <qcameraimageprocessing.h>
#include <qmediaserviceprovider.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QAbstractVideoSurface;
class QVideoWidget;
class QGraphicsVideoItem;
class QCameraPrivate;
class Q_MULTIMEDIA_EXPORT QCamera : public QMediaObject
{
Q_OBJECT
Q_PROPERTY(QCamera::State state READ state NOTIFY stateChanged)
Q_PROPERTY(QCamera::Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QCamera::CaptureMode captureMode READ captureMode WRITE setCaptureMode NOTIFY captureModeChanged)
Q_PROPERTY(QCamera::LockStatus lockStatus READ lockStatus NOTIFY lockStatusChanged)
Q_ENUMS(Status)
Q_ENUMS(State)
Q_ENUMS(CaptureMode)
Q_ENUMS(Error)
Q_ENUMS(LockStatus)
Q_ENUMS(LockChangeReason)
Q_ENUMS(LockType)
public:
enum Status {
UnavailableStatus,
UnloadedStatus,
LoadingStatus,
LoadedStatus,
StandbyStatus,
StartingStatus,
ActiveStatus
};
enum State {
UnloadedState,
LoadedState,
ActiveState
};
enum CaptureMode
{
CaptureStillImage,
CaptureVideo
};
enum Error
{
NoError,
CameraError,
InvalidRequestError,
ServiceMissingError,
NotSupportedFeatureError
};
enum LockStatus
{
Unlocked,
Searching,
Locked
};
enum LockChangeReason {
UserRequest,
LockAcquired,
LockFailed,
LockLost,
LockTemporaryLost
};
enum LockType
{
NoLock = 0,
LockExposure = 0x01,
LockWhiteBalance = 0x02,
LockFocus = 0x04
};
Q_DECLARE_FLAGS(LockTypes, LockType)
QCamera(QObject *parent = 0, QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider());
QCamera(const QByteArray& device, QObject *parent = 0);
~QCamera();
static QList<QByteArray> availableDevices();
static QString deviceDescription(const QByteArray &device);
bool isAvailable() const;
QtMultimedia::AvailabilityError availabilityError() const;
State state() const;
Status status() const;
CaptureMode captureMode() const;
bool isCaptureModeSupported(CaptureMode mode) const;
QCameraExposure *exposure() const;
QCameraFocus *focus() const;
QCameraImageProcessing *imageProcessing() const;
void setViewfinder(QVideoWidget *viewfinder);
void setViewfinder(QGraphicsVideoItem *viewfinder);
void setViewfinder(QAbstractVideoSurface *surface);
Error error() const;
QString errorString() const;
QCamera::LockTypes supportedLocks() const;
QCamera::LockTypes requestedLocks() const;
QCamera::LockStatus lockStatus() const;
QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
public Q_SLOTS:
void setCaptureMode(QCamera::CaptureMode mode);
void load();
void unload();
void start();
void stop();
void searchAndLock();
void unlock();
void searchAndLock(QCamera::LockTypes locks);
void unlock(QCamera::LockTypes locks);
Q_SIGNALS:
void stateChanged(QCamera::State);
void captureModeChanged(QCamera::CaptureMode);
void statusChanged(QCamera::Status);
void locked();
void lockFailed();
void lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
void lockStatusChanged(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason);
void error(QCamera::Error);
private:
Q_DISABLE_COPY(QCamera)
Q_DECLARE_PRIVATE(QCamera)
Q_PRIVATE_SLOT(d_func(), void _q_preparePropertyChange(int))
Q_PRIVATE_SLOT(d_func(), void _q_restartCamera())
Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
Q_PRIVATE_SLOT(d_func(), void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason))
Q_PRIVATE_SLOT(d_func(), void _q_updateState(QCamera::State))
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QCamera::LockTypes)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCamera::State)
Q_DECLARE_METATYPE(QCamera::Status)
Q_DECLARE_METATYPE(QCamera::Error)
Q_DECLARE_METATYPE(QCamera::CaptureMode)
Q_DECLARE_METATYPE(QCamera::LockType)
Q_DECLARE_METATYPE(QCamera::LockStatus)
Q_DECLARE_METATYPE(QCamera::LockChangeReason)
Q_MEDIA_ENUM_DEBUG(QCamera, State)
Q_MEDIA_ENUM_DEBUG(QCamera, Status)
Q_MEDIA_ENUM_DEBUG(QCamera, Error)
Q_MEDIA_ENUM_DEBUG(QCamera, CaptureMode)
Q_MEDIA_ENUM_DEBUG(QCamera, LockType)
Q_MEDIA_ENUM_DEBUG(QCamera, LockStatus)
Q_MEDIA_ENUM_DEBUG(QCamera, LockChangeReason)
QT_END_HEADER
#endif // QCAMERA_H

View File

@@ -0,0 +1,117 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameracapturebufferformatcontrol.h>
QT_BEGIN_NAMESPACE
/*!
\class QCameraCaptureBufferFormatControl
\brief The QCameraCaptureBufferFormatControl class provides a control for setting the capture buffer format.
The format is of type QVideoFrame::PixelFormat.
\inmodule QtMultimedia
\ingroup multimedia-serv
The interface name of QCameraCaptureBufferFormatControl is \c com.nokia.Qt.QCameraCaptureBufferFormatControl/1.0 as
defined in QCameraCaptureBufferFormatControl_iid.
\sa QMediaService::requestControl()
*/
/*!
\macro QCameraCaptureBufferFormatControl_iid
\c com.nokia.Qt.QCameraCaptureBufferFormatControl/1.0
Defines the interface name of the QCameraCaptureBufferFormatControl class.
\relates QCameraCaptureBufferFormatControl
*/
/*!
Constructs a new image buffer capture format control object with the given \a parent
*/
QCameraCaptureBufferFormatControl::QCameraCaptureBufferFormatControl(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys an image buffer capture format control.
*/
QCameraCaptureBufferFormatControl::~QCameraCaptureBufferFormatControl()
{
}
/*!
\fn QCameraCaptureBufferFormatControl::supportedBufferFormats() const
Returns the list of the supported buffer capture formats.
\since 1.2
*/
/*!
\fn QCameraCaptureBufferFormatControl::bufferFormat() const
Returns the current buffer capture format.
\since 1.2
*/
/*!
\fn QCameraCaptureBufferFormatControl::setBufferFormat(QVideoFrame::PixelFormat format)
Sets the buffer capture \a format.
\since 1.2
*/
/*!
\fn QCameraCaptureBufferFormatControl::bufferFormatChanged(QVideoFrame::PixelFormat format)
Signals the buffer image capture format changed to \a format.
\since 1.2
*/
#include "moc_qcameracapturebufferformatcontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERACAPTUREBUFFERFORMATCONTROL_H
#define QCAMERACAPTUREBUFFERFORMATCONTROL_H
#include <qmediacontrol.h>
#include <qcameraimagecapture.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraCaptureBufferFormatControl : public QMediaControl
{
Q_OBJECT
public:
~QCameraCaptureBufferFormatControl();
virtual QList<QVideoFrame::PixelFormat> supportedBufferFormats() const = 0;
virtual QVideoFrame::PixelFormat bufferFormat() const = 0;
virtual void setBufferFormat(QVideoFrame::PixelFormat format) = 0;
Q_SIGNALS:
void bufferFormatChanged(QVideoFrame::PixelFormat);
protected:
QCameraCaptureBufferFormatControl(QObject* parent = 0);
};
#define QCameraCaptureBufferFormatControl_iid "com.nokia.Qt.QCameraCaptureBufferFormatControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraCaptureBufferFormatControl, QCameraCaptureBufferFormatControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameracapturedestinationcontrol.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
/*!
\class QCameraCaptureDestinationControl
\brief The QCameraCaptureDestinationControl class provides a control for setting capture destination.
Depending on backend capabilities capture to file, buffer or both can be supported.
\inmodule QtMultimedia
\ingroup multimedia-serv
The interface name of QCameraCaptureDestinationControl is \c com.nokia.Qt.QCameraCaptureDestinationControl/1.0 as
defined in QCameraCaptureDestinationControl_iid.
\sa QMediaService::requestControl()
*/
/*!
\macro QCameraCaptureDestinationControl_iid
\c com.nokia.Qt.QCameraCaptureDestinationControl/1.0
Defines the interface name of the QCameraCaptureDestinationControl class.
\relates QCameraCaptureDestinationControl
*/
/*!
Constructs a new image capture destination control object with the given \a parent
*/
QCameraCaptureDestinationControl::QCameraCaptureDestinationControl(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys an image capture destination control.
*/
QCameraCaptureDestinationControl::~QCameraCaptureDestinationControl()
{
}
/*!
\fn QCameraCaptureDestinationControl::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
Returns true if the capture \a destination is supported; and false if it is not.
\since 1.2
*/
/*!
\fn QCameraCaptureDestinationControl::captureDestination() const
Returns the current capture \a destination. The default destination is QCameraImageCapture::CaptureToFile.
\since 1.2
*/
/*!
\fn QCameraCaptureDestinationControl::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
Sets the capture \a destination.
\since 1.2
*/
/*!
\fn QCameraCaptureDestinationControl::captureDestinationChanged(QCameraImageCapture::CaptureDestinations destination)
Signals the image capture \a destination changed.
\since 1.2
*/
#include "moc_qcameracapturedestinationcontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERACAPTUREDESTINATIONCONTROL_H
#define QCAMERACAPTUREDESTINATIONCONTROL_H
#include <qmediacontrol.h>
#include <qcameraimagecapture.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraCaptureDestinationControl : public QMediaControl
{
Q_OBJECT
public:
~QCameraCaptureDestinationControl();
virtual bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const = 0;
virtual QCameraImageCapture::CaptureDestinations captureDestination() const = 0;
virtual void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) = 0;
Q_SIGNALS:
void captureDestinationChanged(QCameraImageCapture::CaptureDestinations);
protected:
QCameraCaptureDestinationControl(QObject* parent = 0);
};
#define QCameraCaptureDestinationControl_iid "com.nokia.Qt.QCameraCaptureDestinationControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraCaptureDestinationControl, QCameraCaptureDestinationControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,215 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameracontrol.h>
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QCameraControl
\brief The QCameraControl class is an abstract base class for
classes that control still cameras or video cameras.
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.1
This service is provided by a QMediaService object via
QMediaService::control(). It is used by QCamera.
The interface name of QCameraControl is \c com.nokia.Qt.QCameraControl/1.0 as
defined in QCameraControl_iid.
\sa QMediaService::requestControl(), QCamera
*/
/*!
\macro QCameraControl_iid
\c com.nokia.Qt.QCameraControl/1.0
Defines the interface name of the QCameraControl class.
\relates QCameraControl
*/
/*!
Constructs a camera control object with \a parent.
*/
QCameraControl::QCameraControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
Destruct the camera control object.
*/
QCameraControl::~QCameraControl()
{
}
/*!
\fn QCameraControl::state() const
Returns the state of the camera service.
\since 1.1
\sa QCamera::state
*/
/*!
\fn QCameraControl::setState(QCamera::State state)
Sets the camera \a state.
State changes are synchronous and indicate user intention,
while camera status is used as a feedback mechanism to inform application about backend status.
Status changes are reported asynchronously with QCameraControl::statusChanged() signal.
\since 1.1
\sa QCamera::State
*/
/*!
\fn void QCameraControl::stateChanged(QCamera::State state)
Signal emitted when the camera \a state changes.
In most cases the state chage is caused by QCameraControl::setState(),
but if critical error has occurred the state changes to QCamera::UnloadedState.
\since 1.1
*/
/*!
\fn QCameraControl::status() const
Returns the status of the camera service.
\since 1.1
\sa QCamera::state
*/
/*!
\fn void QCameraControl::statusChanged(QCamera::Status status)
Signal emitted when the camera \a status changes.
\since 1.1
*/
/*!
\fn void QCameraControl::error(int error, const QString &errorString)
Signal emitted when an error occurs with error code \a error and
a description of the error \a errorString.
\since 1.1
*/
/*!
\fn Camera::CaptureMode QCameraControl::captureMode() const = 0
Returns the current capture mode.
\since 1.1
*/
/*!
\fn void QCameraControl::setCaptureMode(QCamera::CaptureMode mode) = 0;
Sets the current capture \a mode.
The capture mode changes are synchronous and allowed in any camera state.
If the capture mode is changed while camera is active,
it's recommended to change status to QCamera::LoadedStatus
and start activating the camera in the next event loop
with the status changed to QCamera::StartingStatus.
This allows the capture settings to be applied before camera is started.
Than change the status to QCamera::StartedStatus when the capture mode change is done.
\since 1.1
*/
/*!
\fn bool QCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const = 0;
Returns true if the capture \a mode is suported.
\since 1.1
*/
/*!
\fn QCameraControl::captureModeChanged(QCamera::CaptureMode mode)
Signal emitted when the camera capture \a mode changes.
\since 1.1
*/
/*!
\fn bool QCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
Returns true if backend can effectively apply changing camera properties of \a changeType type
while the camera state is QCamera::Active and camera status matches \a status parameter.
If backend doesn't support applying this change in the active state, it will be stopped
before the settings are changed and restarted after.
Otherwise the backend should apply the change in the current state,
with the camera status indicating the progress, if necessary.
\since 1.1
*/
/*!
\enum QCameraControl::PropertyChangeType
\value CaptureMode Indicates the capture mode is changed.
\value ImageEncodingSettings Image encoder settings are changed, including resolution.
\value VideoEncodingSettings
Video encoder settings are changed, including audio, video and container settings.
\value Viewfinder Viewfinder is changed.
*/
#include "moc_qcameracontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERACONTROL_H
#define QCAMERACONTROL_H
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qcamera.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraControl : public QMediaControl
{
Q_OBJECT
public:
enum PropertyChangeType {
CaptureMode = 1,
ImageEncodingSettings = 2,
VideoEncodingSettings = 3,
Viewfinder = 4
};
~QCameraControl();
virtual QCamera::State state() const = 0;
virtual void setState(QCamera::State state) = 0;
virtual QCamera::Status status() const = 0;
virtual QCamera::CaptureMode captureMode() const = 0;
virtual void setCaptureMode(QCamera::CaptureMode) = 0;
virtual bool isCaptureModeSupported(QCamera::CaptureMode mode) const = 0;
virtual bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const = 0;
Q_SIGNALS:
void stateChanged(QCamera::State);
void statusChanged(QCamera::Status);
void error(int error, const QString &errorString);
void captureModeChanged(QCamera::CaptureMode);
protected:
QCameraControl(QObject* parent = 0);
};
#define QCameraControl_iid "com.nokia.Qt.QCameraControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraControl, QCameraControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QCAMERACONTROL_H

View File

@@ -0,0 +1,646 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <QDebug>
#include <qcameraexposure.h>
#include <qcamera.h>
#include <qmediaobject_p.h>
#include <qcameraexposurecontrol.h>
#include <qcameraflashcontrol.h>
#include <qmetaobject.h>
QT_BEGIN_NAMESPACE
/*!
\class QCameraExposure
\brief The QCameraExposure class provides interface for exposure related camera settings.
\inmodule QtMultimedia
\ingroup camera
\since 1.1
*/
//#define DEBUG_EXPOSURE_CHANGES 1
#ifdef DEBUG_EXPOSURE_CHANGES
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
#endif
namespace
{
class CameraExposureRegisterMetaTypes
{
public:
CameraExposureRegisterMetaTypes()
{
qRegisterMetaType<QCameraExposure::ExposureMode>("QCameraExposure::ExposureMode");
qRegisterMetaType<QCameraExposure::FlashModes>("QCameraExposure::FlashModes");
qRegisterMetaType<QCameraExposure::MeteringMode>("QCameraExposure::MeteringMode");
}
} _registerCameraExposureMetaTypes;
}
class QCameraExposurePrivate
{
Q_DECLARE_NON_CONST_PUBLIC(QCameraExposure)
public:
void initControls();
QCameraExposure *q_ptr;
QCamera *camera;
QCameraExposureControl *exposureControl;
QCameraFlashControl *flashControl;
void _q_exposureParameterChanged(int parameter);
void _q_exposureParameterRangeChanged(int parameter);
};
void QCameraExposurePrivate::initControls()
{
Q_Q(QCameraExposure);
QMediaService *service = camera->service();
exposureControl = 0;
flashControl = 0;
if (service) {
exposureControl = qobject_cast<QCameraExposureControl *>(service->requestControl(QCameraExposureControl_iid));
flashControl = qobject_cast<QCameraFlashControl *>(service->requestControl(QCameraFlashControl_iid));
}
if (exposureControl) {
q->connect(exposureControl, SIGNAL(exposureParameterChanged(int)),
q, SLOT(_q_exposureParameterChanged(int)));
q->connect(exposureControl, SIGNAL(exposureParameterRangeChanged(int)),
q, SLOT(_q_exposureParameterRangeChanged(int)));
}
if (flashControl)
q->connect(flashControl, SIGNAL(flashReady(bool)), q, SIGNAL(flashReady(bool)));
}
void QCameraExposurePrivate::_q_exposureParameterChanged(int parameter)
{
Q_Q(QCameraExposure);
#if DEBUG_EXPOSURE_CHANGES
qDebug() << "Exposure parameter changed:"
<< ENUM_NAME(QCameraExposureControl, "ExposureParameter", parameter)
<< exposureControl->exposureParameter(QCameraExposureControl::ExposureParameter(parameter));
#endif
switch (parameter) {
case QCameraExposureControl::ISO:
emit q->isoSensitivityChanged(q->isoSensitivity());
break;
case QCameraExposureControl::Aperture:
emit q->apertureChanged(q->aperture());
break;
case QCameraExposureControl::ShutterSpeed:
emit q->shutterSpeedChanged(q->shutterSpeed());
break;
case QCameraExposureControl::ExposureCompensation:
emit q->exposureCompensationChanged(q->exposureCompensation());
break;
}
}
void QCameraExposurePrivate::_q_exposureParameterRangeChanged(int parameter)
{
Q_Q(QCameraExposure);
switch (parameter) {
case QCameraExposureControl::Aperture:
emit q->apertureRangeChanged();
break;
case QCameraExposureControl::ShutterSpeed:
emit q->shutterSpeedRangeChanged();
break;
}
}
/*!
Construct a QCameraExposure from service \a provider and \a parent.
*/
QCameraExposure::QCameraExposure(QCamera *parent):
QObject(parent), d_ptr(new QCameraExposurePrivate)
{
Q_D(QCameraExposure);
d->camera = parent;
d->q_ptr = this;
d->initControls();
}
/*!
Destroys the camera exposure object.
*/
QCameraExposure::~QCameraExposure()
{
Q_D(QCameraExposure);
if (d->exposureControl)
d->camera->service()->releaseControl(d->exposureControl);
}
/*!
Returns true if exposure settings are supported by this camera.
\since 1.1
*/
bool QCameraExposure::isAvailable() const
{
return d_func()->exposureControl != 0;
}
/*!
\property QCameraExposure::flashMode
\brief The flash mode being used.
Usually the single QCameraExposure::FlashMode flag is used,
but some non conflicting flags combination are also allowed,
like QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain.
\since 1.1
\sa QCameraExposure::isFlashModeSupported(), QCameraExposure::isFlashReady()
*/
QCameraExposure::FlashModes QCameraExposure::flashMode() const
{
return d_func()->flashControl ? d_func()->flashControl->flashMode() : QCameraExposure::FlashOff;
}
void QCameraExposure::setFlashMode(QCameraExposure::FlashModes mode)
{
if (d_func()->flashControl)
d_func()->flashControl->setFlashMode(mode);
}
/*!
Returns true if the flash \a mode is supported.
\since 1.1
*/
bool QCameraExposure::isFlashModeSupported(QCameraExposure::FlashModes mode) const
{
return d_func()->flashControl ? d_func()->flashControl->isFlashModeSupported(mode) : false;
}
/*!
Returns true if flash is charged.
*/
bool QCameraExposure::isFlashReady() const
{
return d_func()->flashControl ? d_func()->flashControl->isFlashReady() : false;
}
/*!
\property QCameraExposure::exposureMode
\brief The exposure mode being used.
\since 1.1
\sa QCameraExposure::isExposureModeSupported()
*/
QCameraExposure::ExposureMode QCameraExposure::exposureMode() const
{
return d_func()->exposureControl ? d_func()->exposureControl->exposureMode() : QCameraExposure::ExposureAuto;
}
void QCameraExposure::setExposureMode(QCameraExposure::ExposureMode mode)
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureMode(mode);
}
/*!
Returns true if the exposure \a mode is supported.
\since 1.1
*/
bool QCameraExposure::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
{
return d_func()->exposureControl ?
d_func()->exposureControl->isExposureModeSupported(mode) : false;
}
/*!
\property QCameraExposure::exposureCompensation
\brief Exposure compensation in EV units.
Exposure compensation property allows to adjust the automatically calculated exposure.
\since 1.1
*/
qreal QCameraExposure::exposureCompensation() const
{
if (d_func()->exposureControl)
return d_func()->exposureControl->exposureParameter(QCameraExposureControl::ExposureCompensation).toReal();
else
return 0;
}
void QCameraExposure::setExposureCompensation(qreal ev)
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ExposureCompensation, QVariant(ev));
}
/*!
\property QCameraExposure::meteringMode
\brief The metering mode being used.
\since 1.1
\sa QCameraExposure::isMeteringModeSupported()
*/
QCameraExposure::MeteringMode QCameraExposure::meteringMode() const
{
return d_func()->exposureControl ? d_func()->exposureControl->meteringMode() : QCameraExposure::MeteringMatrix;
}
void QCameraExposure::setMeteringMode(QCameraExposure::MeteringMode mode)
{
if (d_func()->exposureControl)
d_func()->exposureControl->setMeteringMode(mode);
}
/*!
Returns true if the metering \a mode is supported.
\since 1.1
*/
bool QCameraExposure::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
{
return d_func()->exposureControl ? d_func()->exposureControl->isMeteringModeSupported(mode) : false;
}
int QCameraExposure::isoSensitivity() const
{
if (d_func()->exposureControl)
return d_func()->exposureControl->exposureParameter(QCameraExposureControl::ISO).toInt();
return -1;
}
/*!
Returns the list of ISO senitivities camera supports.
If the camera supports arbitrary ISO sensitivities within the supported range,
*\a continuous is set to true, otherwise *\a continuous is set to false.
\since 1.1
*/
QList<int> QCameraExposure::supportedIsoSensitivities(bool *continuous) const
{
QList<int> res;
QCameraExposureControl *control = d_func()->exposureControl;
if (!control)
return res;
foreach (const QVariant &value,
control->supportedParameterRange(QCameraExposureControl::ISO)) {
bool ok = false;
int intValue = value.toInt(&ok);
if (ok)
res.append(intValue);
else
qWarning() << "Incompatible ISO value type, int is expected";
}
if (continuous)
*continuous = control->exposureParameterFlags(QCameraExposureControl::ISO) &
QCameraExposureControl::ContinuousRange;
return res;
}
/*!
\fn QCameraExposure::setManualIsoSensitivity(int iso)
Sets the manual sensitivity to \a iso
\since 1.1
*/
void QCameraExposure::setManualIsoSensitivity(int iso)
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ISO, QVariant(iso));
}
/*!
\fn QCameraExposure::setAutoIsoSensitivity()
Turn on auto sensitivity
\since 1.1
*/
void QCameraExposure::setAutoIsoSensitivity()
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ISO, QVariant());
}
/*!
\property QCameraExposure::shutterSpeed
\brief Camera's shutter speed in seconds.
\since 1.1
\sa supportedShutterSpeeds(), setAutoShutterSpeed(), setManualShutterSpeed()
*/
/*!
\fn QCameraExposure::shutterSpeedChanged(qreal speed)
Signals that a camera's shutter \a speed has changed.
\since 1.1
*/
/*!
\property QCameraExposure::isoSensitivity
\brief The sensor ISO sensitivity.
\sa supportedIsoSensitivities(), setAutoIsoSensitivity(), setManualIsoSensitivity()
\since 1.1
*/
/*!
\property QCameraExposure::aperture
\brief Lens aperture is specified as an F number, the ratio of the focal length to effective aperture diameter.
\since 1.1
\sa supportedApertures(), setAutoAperture(), setManualAperture()
*/
qreal QCameraExposure::aperture() const
{
if (d_func()->exposureControl)
return d_func()->exposureControl->exposureParameter(QCameraExposureControl::Aperture).toReal();
return -1.0;
}
/*!
Returns the list of aperture values camera supports.
The apertures list can change depending on the focal length,
in such a case the apertureRangeChanged() signal is emitted.
If the camera supports arbitrary aperture values within the supported range,
*\a continuous is set to true, otherwise *\a continuous is set to false.
\since 1.1
*/
QList<qreal> QCameraExposure::supportedApertures(bool * continuous) const
{
QList<qreal> res;
QCameraExposureControl *control = d_func()->exposureControl;
if (!control)
return res;
foreach (const QVariant &value,
control->supportedParameterRange(QCameraExposureControl::Aperture)) {
bool ok = false;
qreal realValue = value.toReal(&ok);
if (ok)
res.append(realValue);
else
qWarning() << "Incompatible aperture value type, qreal is expected";
}
if (continuous)
*continuous = control->exposureParameterFlags(QCameraExposureControl::Aperture) &
QCameraExposureControl::ContinuousRange;
return res;
}
/*!
\fn QCameraExposure::setManualAperture(qreal aperture)
Sets the manual camera \a aperture value.
\since 1.1
*/
void QCameraExposure::setManualAperture(qreal aperture)
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::Aperture, QVariant(aperture));
}
/*!
\fn QCameraExposure::setAutoAperture()
Turn on auto aperture
\since 1.1
*/
void QCameraExposure::setAutoAperture()
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::Aperture, QVariant());
}
/*!
Returns the current shutter speed in seconds.
\since 1.1
*/
qreal QCameraExposure::shutterSpeed() const
{
if (d_func()->exposureControl)
return d_func()->exposureControl->exposureParameter(QCameraExposureControl::ShutterSpeed).toReal();
return -1.0;
}
/*!
Returns the list of shutter speed values in seconds camera supports.
If the camera supports arbitrary shutter speed values within the supported range,
*\a continuous is set to true, otherwise *\a continuous is set to false.
\since 1.1
*/
QList<qreal> QCameraExposure::supportedShutterSpeeds(bool *continuous) const
{
QList<qreal> res;
QCameraExposureControl *control = d_func()->exposureControl;
if (!control)
return res;
foreach (const QVariant &value,
control->supportedParameterRange(QCameraExposureControl::ShutterSpeed)) {
bool ok = false;
qreal realValue = value.toReal(&ok);
if (ok)
res.append(realValue);
else
qWarning() << "Incompatible shutter speed value type, qreal is expected";
}
if (continuous)
*continuous = control->exposureParameterFlags(QCameraExposureControl::ShutterSpeed) &
QCameraExposureControl::ContinuousRange;
return res;
}
/*!
Set the manual shutter speed to \a seconds
\since 1.1
*/
void QCameraExposure::setManualShutterSpeed(qreal seconds)
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ShutterSpeed, QVariant(seconds));
}
/*!
Turn on auto shutter speed
\since 1.1
*/
void QCameraExposure::setAutoShutterSpeed()
{
if (d_func()->exposureControl)
d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ShutterSpeed, QVariant());
}
/*!
\enum QCameraExposure::FlashMode
\value FlashOff Flash is Off.
\value FlashOn Flash is On.
\value FlashAuto Automatic flash.
\value FlashRedEyeReduction Red eye reduction flash.
\value FlashFill Use flash to fillin shadows.
\value FlashTorch Constant light source, useful for focusing and video capture.
\value FlashSlowSyncFrontCurtain
Use the flash in conjunction with a slow shutter speed.
This mode allows better exposure of distant objects and/or motion blur effect.
\value FlashSlowSyncRearCurtain
The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure.
\value FlashManual Flash power is manualy set.
*/
/*!
\enum QCameraExposure::ExposureMode
\value ExposureManual Manual mode.
\value ExposureAuto Automatic mode.
\value ExposureNight Night mode.
\value ExposureBacklight Backlight exposure mode.
\value ExposureSpotlight Spotlight exposure mode.
\value ExposureSports Spots exposure mode.
\value ExposureSnow Snow exposure mode.
\value ExposureBeach Beach exposure mode.
\value ExposureLargeAperture Use larger aperture with small depth of field.
\value ExposureSmallAperture Use smaller aperture.
\value ExposurePortrait Portrait exposure mode.
\value ExposureModeVendor The base value for device specific exposure modes.
*/
/*!
\enum QCameraExposure::MeteringMode
\value MeteringAverage Center weighted average metering mode.
\value MeteringSpot Spot metering mode.
\value MeteringMatrix Matrix metering mode.
*/
/*!
\property QCameraExposure::flashReady
\brief Indicates if the flash is charged and ready to use.
\since 1.1
*/
/*!
\fn void QCameraExposure::flashReady(bool ready)
Signal the flash \a ready status has changed.
\since 1.1
*/
/*!
\fn void QCameraExposure::apertureChanged(qreal value)
Signal emitted when aperature changes to \a value.
\since 1.1
*/
/*!
\fn void QCameraExposure::apertureRangeChanged()
Signal emitted when aperature range has changed.
\since 1.1
*/
/*!
\fn void QCameraExposure::shutterSpeedRangeChanged()
Signal emitted when the shutter speed range has changed.
\since 1.1
*/
/*!
\fn void QCameraExposure::isoSensitivityChanged(int value)
Signal emitted when sensitivity changes to \a value.
\since 1.1
*/
/*!
\fn void QCameraExposure::exposureCompensationChanged(qreal value)
Signal emitted when the exposure compensation changes to \a value.
\since 1.1
*/
#include "moc_qcameraexposure.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,185 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAEXPOSURE_H
#define QCAMERAEXPOSURE_H
#include <qmediaobject.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QCamera;
class QCameraExposurePrivate;
class Q_MULTIMEDIA_EXPORT QCameraExposure : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal aperture READ aperture NOTIFY apertureChanged)
Q_PROPERTY(qreal shutterSpeed READ shutterSpeed NOTIFY shutterSpeedChanged)
Q_PROPERTY(int isoSensitivity READ isoSensitivity NOTIFY isoSensitivityChanged)
Q_PROPERTY(qreal exposureCompensation READ exposureCompensation WRITE setExposureCompensation NOTIFY exposureCompensationChanged)
Q_PROPERTY(bool flashReady READ isFlashReady NOTIFY flashReady)
Q_PROPERTY(QCameraExposure::FlashModes flashMode READ flashMode WRITE setFlashMode)
Q_PROPERTY(QCameraExposure::ExposureMode exposureMode READ exposureMode WRITE setExposureMode)
Q_PROPERTY(QCameraExposure::MeteringMode meteringMode READ meteringMode WRITE setMeteringMode)
Q_ENUMS(FlashMode)
Q_ENUMS(ExposureMode)
Q_ENUMS(MeteringMode)
public:
enum FlashMode {
FlashAuto = 0x1,
FlashOff = 0x2,
FlashOn = 0x4,
FlashRedEyeReduction = 0x8,
FlashFill = 0x10,
FlashTorch = 0x20,
FlashSlowSyncFrontCurtain = 0x40,
FlashSlowSyncRearCurtain = 0x80,
FlashManual = 0x100
};
Q_DECLARE_FLAGS(FlashModes, FlashMode)
enum ExposureMode {
ExposureAuto = 0,
ExposureManual = 1,
ExposurePortrait = 2,
ExposureNight = 3,
ExposureBacklight = 4,
ExposureSpotlight = 5,
ExposureSports = 6,
ExposureSnow = 7,
ExposureBeach = 8,
ExposureLargeAperture = 9,
ExposureSmallAperture = 10,
ExposureModeVendor = 1000
};
enum MeteringMode {
MeteringMatrix = 1,
MeteringAverage = 2,
MeteringSpot = 3
};
bool isAvailable() const;
FlashModes flashMode() const;
bool isFlashModeSupported(FlashModes mode) const;
bool isFlashReady() const;
ExposureMode exposureMode() const;
bool isExposureModeSupported(ExposureMode mode) const;
qreal exposureCompensation() const;
MeteringMode meteringMode() const;
bool isMeteringModeSupported(MeteringMode mode) const;
int isoSensitivity() const;
QList<int> supportedIsoSensitivities(bool *continuous = 0) const;
qreal aperture() const;
QList<qreal> supportedApertures(bool *continuous = 0) const;
qreal shutterSpeed() const;
QList<qreal> supportedShutterSpeeds(bool *continuous = 0) const;
public Q_SLOTS:
void setFlashMode(FlashModes mode);
void setExposureMode(ExposureMode mode);
void setExposureCompensation(qreal ev);
void setMeteringMode(MeteringMode mode);
void setManualIsoSensitivity(int iso);
void setAutoIsoSensitivity();
void setManualAperture(qreal aperture);
void setAutoAperture();
void setManualShutterSpeed(qreal seconds);
void setAutoShutterSpeed();
Q_SIGNALS:
void flashReady(bool);
void apertureChanged(qreal);
void apertureRangeChanged();
void shutterSpeedChanged(qreal);
void shutterSpeedRangeChanged();
void isoSensitivityChanged(int);
void exposureCompensationChanged(qreal);
private:
friend class QCamera;
explicit QCameraExposure(QCamera *parent = 0);
virtual ~QCameraExposure();
Q_DISABLE_COPY(QCameraExposure)
Q_DECLARE_PRIVATE(QCameraExposure)
Q_PRIVATE_SLOT(d_func(), void _q_exposureParameterChanged(int))
Q_PRIVATE_SLOT(d_func(), void _q_exposureParameterRangeChanged(int))
QCameraExposurePrivate *d_ptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraExposure::FlashModes)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCameraExposure::ExposureMode)
Q_DECLARE_METATYPE(QCameraExposure::FlashModes)
Q_DECLARE_METATYPE(QCameraExposure::MeteringMode)
Q_MEDIA_ENUM_DEBUG(QCameraExposure, ExposureMode)
Q_MEDIA_ENUM_DEBUG(QCameraExposure, FlashMode)
Q_MEDIA_ENUM_DEBUG(QCameraExposure, MeteringMode)
QT_END_HEADER
#endif // QCAMERAEXPOSURE_H

View File

@@ -0,0 +1,252 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameraexposurecontrol.h>
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QCameraExposureControl
\brief The QCameraExposureControl class allows controlling camera exposure parameters.
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.1
You can adjust a number of parameters that will affect images and video taken with
the corresponding QCamera object.
There are a number of different parameters that can be adjusted, including:
\table
\row
\header
\
\endtable
The interface name of QCameraExposureControl is \c com.nokia.Qt.QCameraExposureControl/1.0 as
defined in QCameraExposureControl_iid.
\sa QCamera
*/
/*!
\macro QCameraExposureControl_iid
\c com.nokia.Qt.QCameraExposureControl/1.0
Defines the interface name of the QCameraExposureControl class.
\relates QCameraExposureControl
*/
/*!
Constructs a camera exposure control object with \a parent.
*/
QCameraExposureControl::QCameraExposureControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
Destroys the camera control object.
*/
QCameraExposureControl::~QCameraExposureControl()
{
}
/*!
\fn QCamera::ExposureMode QCameraExposureControl::exposureMode() const
Returns the exposure mode.
\since 1.1
*/
/*!
\fn void QCameraExposureControl::setExposureMode(QCameraExposure::ExposureMode mode)
Set the exposure mode to \a mode.
\since 1.1
*/
/*!
\fn bool QCameraExposureControl::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
Returns true if the exposure \a mode is supported.
\since 1.1
*/
/*!
\fn QCameraExposure::MeteringMode QCameraExposureControl::meteringMode() const
Returns the current metering mode.
\since 1.1
*/
/*!
\fn void QCameraExposureControl::setMeteringMode(QCameraExposure::MeteringMode mode)
Set the metering mode to \a mode.
\since 1.1
*/
/*!
\fn bool QCameraExposureControl::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
Returns true if the metering \a mode is supported.
\since 1.1
*/
/*!
\enum QCameraExposureControl::ExposureParameter
\value InvalidParameter
Parameter is invalid.
\value ISO
Camera ISO sensitivity, specified as integer value.
\value Aperture
Lens aperture is specified as an qreal F number.
The supported apertures list can change depending on the focal length,
in such a case the exposureParameterRangeChanged() signal is emitted.
\value ShutterSpeed
Shutter speed in seconds, specified as qreal.
\value ExposureCompensation
Exposure compensation, specified as qreal EV value.
\value FlashPower
Manual flash power, specified as qreal value.
Accepted power range is [0..1.0],
with 0 value means no flash and 1.0 corresponds to full flash power.
This value is only used in the \l{QCameraExposure::FlashManual}{manual flash mode}.
\value FlashCompensation
Flash compensation, specified as qreal EV value.
\value ExtendedExposureParameter
The base value for platform specific extended parameters.
For such parameters the sequential values starting from ExtendedExposureParameter shuld be used.
*/
/*!
\enum QCameraExposureControl::ParameterFlag
\value AutomaticValue
Use the automatic values for parameters.
\value ReadOnly
Parameters are read only.
\value ContinuousRange
Parameters are continuous in their range.
*/
/*!
\fn QCameraExposureControl::isParameterSupported(ExposureParameter parameter) const
Returns true is exposure \a parameter is supported by backend.
\since 1.1
*/
/*!
\fn QCameraExposureControl::exposureParameter(ExposureParameter parameter) const
Returns the exposure \a parameter value, or invalid QVariant() if the value is unknown or not supported.
\since 1.1
*/
/*!
\fn QCameraExposureControl::exposureParameterFlags(ExposureParameter parameter) const
Returns the properties of exposure \a parameter.
\since 1.1
*/
/*!
\fn QCameraExposureControl::supportedParameterRange(ExposureParameter parameter) const
Returns the list of supported \a parameter values;
\since 1.1
*/
/*!
\fn bool QCameraExposureControl::setExposureParameter(ExposureParameter parameter, const QVariant& value)
Set the exposure \a parameter to \a value.
If a null or invalid QVariant is passed, backend should choose the value automatically,
and if possible report the actual value to user with QCameraExposureControl::exposureParameter().
Returns true if parameter is supported and value is correct.
\since 1.1
*/
/*!
\fn QCameraExposureControl::extendedParameterName(ExposureParameter parameter)
Returns the extended exposure \a parameter name.
\since 1.1
*/
/*!
\fn void QCameraExposureControl::flashReady(bool ready)
Signal emitted when flash state changes, flash is charged \a ready.
\since 1.1
*/
/*!
\fn void QCameraExposureControl::exposureParameterChanged(int parameter)
Signal emitted when the exposure \a parameter has changed.
\since 1.1
*/
/*!
\fn void QCameraExposureControl::exposureParameterRangeChanged(int parameter)
Signal emitted when the exposure \a parameter range has changed.
\since 1.1
*/
#include "moc_qcameraexposurecontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,124 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAEXPOSURECONTROL_H
#define QCAMERAEXPOSURECONTROL_H
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qcameraexposure.h>
#include <qcamera.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraExposureControl : public QMediaControl
{
Q_OBJECT
Q_ENUMS(ExposureParameter)
public:
~QCameraExposureControl();
enum ExposureParameter {
InvalidParameter = 0,
ISO = 1,
Aperture = 2,
ShutterSpeed = 3,
ExposureCompensation = 4,
FlashPower = 5,
FlashCompensation = 6,
ExtendedExposureParameter = 1000
};
enum ParameterFlag {
AutomaticValue = 0x01,
ReadOnly = 0x02,
ContinuousRange = 0x04
};
Q_DECLARE_FLAGS(ParameterFlags, ParameterFlag)
virtual QCameraExposure::ExposureMode exposureMode() const = 0;
virtual void setExposureMode(QCameraExposure::ExposureMode mode) = 0;
virtual bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const = 0;
virtual QCameraExposure::MeteringMode meteringMode() const = 0;
virtual void setMeteringMode(QCameraExposure::MeteringMode mode) = 0;
virtual bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const = 0;
virtual bool isParameterSupported(ExposureParameter parameter) const = 0;
virtual QVariant exposureParameter(ExposureParameter parameter) const = 0;
virtual ParameterFlags exposureParameterFlags(ExposureParameter parameter) const = 0;
virtual QVariantList supportedParameterRange(ExposureParameter parameter) const = 0;
virtual bool setExposureParameter(ExposureParameter parameter, const QVariant& value) = 0;
virtual QString extendedParameterName(ExposureParameter parameter) = 0;
Q_SIGNALS:
void flashReady(bool);
void exposureParameterChanged(int parameter);
void exposureParameterRangeChanged(int parameter);
protected:
QCameraExposureControl(QObject* parent = 0);
};
#define QCameraExposureControl_iid "com.nokia.Qt.QCameraExposureControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraExposureControl, QCameraExposureControl_iid)
Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraExposureControl::ParameterFlags)
Q_MEDIA_ENUM_DEBUG(QCameraExposureControl, ExposureParameter)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QCAMERAEXPOSURECONTROL_H

View File

@@ -0,0 +1,141 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameraflashcontrol.h>
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QCameraFlashControl
\brief The QCameraFlashControl class allows controlling a camera's flash.
\ingroup multimedia-serv
\inmodule QtMultimedia
\since 1.1
\inmodule QtMultimedia
You can set the type of flash effect used when an image is captured, and test to see
if the flash hardware is ready to fire.
You can retrieve this control from the camera object in the usual way:
Some camera devices may not have flash hardware, or may not be configurable. In that
case, there will be no QCameraFlashControl available.
The interface name of QCameraFlashControl is \c com.nokia.Qt.QCameraFlashControl/1.0 as
defined in QCameraFlashControl_iid.
\sa QCamera
*/
/*!
\macro QCameraFlashControl_iid
\c com.nokia.Qt.QCameraFlashControl/1.0
Defines the interface name of the QCameraFlashControl class.
\relates QCameraFlashControl
*/
/*!
Constructs a camera flash control object with \a parent.
*/
QCameraFlashControl::QCameraFlashControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
Destroys the camera control object.
*/
QCameraFlashControl::~QCameraFlashControl()
{
}
/*!
\fn QCamera::FlashModes QCameraFlashControl::flashMode() const
Returns the current flash mode.
\since 1.1
*/
/*!
\fn void QCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
Set the current flash \a mode.
Usually a single QCameraExposure::FlashMode flag is used,
but some non conflicting flags combination are also allowed,
like QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain.
\since 1.1
*/
/*!
\fn QCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
Return true if the reqested flash \a mode is supported.
Some QCameraExposure::FlashMode values can be combined,
for example QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain
\since 1.1
*/
/*!
\fn bool QCameraFlashControl::isFlashReady() const
Returns true if flash is charged.
\since 1.1
*/
/*!
\fn void QCameraFlashControl::flashReady(bool ready)
Signal emitted when flash state changes to \a ready.
\since 1.1
*/
#include "moc_qcameraflashcontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAFLASHCONTROL_H
#define QCAMERAFLASHCONTROL_H
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qcameraexposure.h>
#include <qcamera.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraFlashControl : public QMediaControl
{
Q_OBJECT
public:
~QCameraFlashControl();
virtual QCameraExposure::FlashModes flashMode() const = 0;
virtual void setFlashMode(QCameraExposure::FlashModes mode) = 0;
virtual bool isFlashModeSupported(QCameraExposure::FlashModes mode) const = 0;
virtual bool isFlashReady() const = 0;
Q_SIGNALS:
void flashReady(bool);
protected:
QCameraFlashControl(QObject* parent = 0);
};
#define QCameraFlashControl_iid "com.nokia.Qt.QCameraFlashControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraFlashControl, QCameraFlashControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QCAMERAFLASHCONTROL_H

View File

@@ -0,0 +1,478 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <QDebug>
#include <qcamera.h>
#include <qcamerafocus.h>
#include <qmediaobject_p.h>
#include <qcameracontrol.h>
#include <qcameraexposurecontrol.h>
#include <qcamerafocuscontrol.h>
#include <qmediarecordercontrol.h>
#include <qcameraimagecapturecontrol.h>
#include <qvideodevicecontrol.h>
QT_BEGIN_NAMESPACE
namespace
{
class CameraFocusRegisterMetaTypes
{
public:
CameraFocusRegisterMetaTypes()
{
qRegisterMetaType<QCameraFocus::FocusModes>("QCameraFocus::FocusModes");
qRegisterMetaType<QCameraFocus::FocusPointMode>("QCameraFocus::FocusPointMode");
}
} _registerCameraFocusMetaTypes;
}
class QCameraFocusZoneData : public QSharedData
{
public:
QCameraFocusZoneData():
status(QCameraFocusZone::Invalid)
{
}
QCameraFocusZoneData(const QRectF &_area, QCameraFocusZone::FocusZoneStatus _status):
area(_area),
status(_status)
{
}
QCameraFocusZoneData(const QCameraFocusZoneData &other):
QSharedData(other),
area(other.area),
status(other.status)
{
}
QCameraFocusZoneData& operator=(const QCameraFocusZoneData &other)
{
area = other.area;
status = other.status;
return *this;
}
QRectF area;
QCameraFocusZone::FocusZoneStatus status;
};
QCameraFocusZone::QCameraFocusZone()
:d(new QCameraFocusZoneData)
{
}
QCameraFocusZone::QCameraFocusZone(const QRectF &area, QCameraFocusZone::FocusZoneStatus status)
:d(new QCameraFocusZoneData(area, status))
{
}
QCameraFocusZone::QCameraFocusZone(const QCameraFocusZone &other)
:d(other.d)
{
}
QCameraFocusZone::~QCameraFocusZone()
{
}
QCameraFocusZone& QCameraFocusZone::operator=(const QCameraFocusZone &other)
{
d = other.d;
return *this;
}
bool QCameraFocusZone::operator==(const QCameraFocusZone &other) const
{
return d == other.d ||
(d->area == other.d->area && d->status == other.d->status);
}
bool QCameraFocusZone::operator!=(const QCameraFocusZone &other) const
{
return !(*this == other);
}
bool QCameraFocusZone::isValid() const
{
return d->status != Invalid && !d->area.isValid();
}
QRectF QCameraFocusZone::area() const
{
return d->area;
}
QCameraFocusZone::FocusZoneStatus QCameraFocusZone::status() const
{
return d->status;
}
void QCameraFocusZone::setStatus(QCameraFocusZone::FocusZoneStatus status)
{
d->status = status;
}
/*!
\class QCameraFocus
\brief The QCameraFocus class provides interface for
focus and zoom related camera settings.
\inmodule QtMultimedia
\ingroup camera
\since 1.1
*/
class QCameraFocusPrivate : public QMediaObjectPrivate
{
Q_DECLARE_NON_CONST_PUBLIC(QCameraFocus)
public:
void initControls();
QCameraFocus *q_ptr;
QCamera *camera;
QCameraFocusControl *focusControl;
};
void QCameraFocusPrivate::initControls()
{
Q_Q(QCameraFocus);
focusControl = 0;
QMediaService *service = camera->service();
if (service)
focusControl = qobject_cast<QCameraFocusControl *>(service->requestControl(QCameraFocusControl_iid));
if (focusControl) {
q->connect(focusControl, SIGNAL(opticalZoomChanged(qreal)), q, SIGNAL(opticalZoomChanged(qreal)));
q->connect(focusControl, SIGNAL(digitalZoomChanged(qreal)), q, SIGNAL(digitalZoomChanged(qreal)));
q->connect(focusControl, SIGNAL(maximumOpticalZoomChanged(qreal)),
q, SIGNAL(maximumOpticalZoomChanged(qreal)));
q->connect(focusControl, SIGNAL(maximumDigitalZoomChanged(qreal)),
q, SIGNAL(maximumDigitalZoomChanged(qreal)));
q->connect(focusControl, SIGNAL(focusZonesChanged()), q, SIGNAL(focusZonesChanged()));
}
}
/*!
Construct a QCameraFocus for \a camera.
*/
QCameraFocus::QCameraFocus(QCamera *camera):
QObject(camera), d_ptr(new QCameraFocusPrivate)
{
Q_D(QCameraFocus);
d->camera = camera;
d->q_ptr = this;
d->initControls();
}
/*!
Destroys the camera focus object.
*/
QCameraFocus::~QCameraFocus()
{
}
/*!
Returns true if focus related settings are supported by this camera.
\since 1.1
*/
bool QCameraFocus::isAvailable() const
{
return d_func()->focusControl != 0;
}
/*!
\property QCameraFocus::focusMode
\brief The current camera focus mode.
\since 1.1
\sa QCameraFocus::isFocusModeSupported()
*/
QCameraFocus::FocusMode QCameraFocus::focusMode() const
{
return d_func()->focusControl ? d_func()->focusControl->focusMode() : QCameraFocus::AutoFocus;
}
void QCameraFocus::setFocusMode(QCameraFocus::FocusMode mode)
{
if (d_func()->focusControl)
d_func()->focusControl->setFocusMode(mode);
}
/*!
Returns true if the focus \a mode is supported by camera.
\since 1.1
*/
bool QCameraFocus::isFocusModeSupported(QCameraFocus::FocusMode mode) const
{
return d_func()->focusControl ? d_func()->focusControl->isFocusModeSupported(mode) : false;
}
/*!
\property QCameraFocus::focusPointMode
\brief The current camera focus point selection mode.
\sa QCameraFocus::isFocusPointModeSupported()
\since 1.1
*/
QCameraFocus::FocusPointMode QCameraFocus::focusPointMode() const
{
return d_func()->focusControl ?
d_func()->focusControl->focusPointMode() :
QCameraFocus::FocusPointAuto;
}
void QCameraFocus::setFocusPointMode(QCameraFocus::FocusPointMode mode)
{
if (d_func()->focusControl)
d_func()->focusControl->setFocusPointMode(mode);
else
qWarning("Focus points mode selection is not supported");
}
/*!
Returns true if focus point \a mode is supported.
\since 1.1
*/
bool QCameraFocus::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
{
return d_func()->focusControl ?
d_func()->focusControl->isFocusPointModeSupported(mode) :
false;
}
/*!
\property QCameraFocus::customFocusPoint
Position of custom focus point, in relative frame coordinates:
QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center.
Custom focus point is used only in FocusPointCustom focus mode.
\since 1.1
*/
QPointF QCameraFocus::customFocusPoint() const
{
return d_func()->focusControl ?
d_func()->focusControl->customFocusPoint() :
QPointF(0.5,0.5);
}
void QCameraFocus::setCustomFocusPoint(const QPointF &point)
{
if (d_func()->focusControl)
d_func()->focusControl->setCustomFocusPoint(point);
else
qWarning("Focus points selection is not supported");
}
/*!
\property QCameraFocus::focusZones
Returns the list of active focus zones.
If QCamera::FocusPointAuto or QCamera::FocusPointFaceDetection focus mode is selected
this method returns the list of zones the camera is actually focused on.
The coordinates system is the same as for custom focus points:
QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center.
\since 1.1
*/
QCameraFocusZoneList QCameraFocus::focusZones() const
{
return d_func()->focusControl ?
d_func()->focusControl->focusZones() :
QCameraFocusZoneList();
}
/*!
Returns the maximum optical zoom
\since 1.1
*/
qreal QCameraFocus::maximumOpticalZoom() const
{
return d_func()->focusControl ? d_func()->focusControl->maximumOpticalZoom() : 1.0;
}
/*!
Returns the maximum digital zoom
\since 1.1
*/
qreal QCameraFocus::maximumDigitalZoom() const
{
return d_func()->focusControl ? d_func()->focusControl->maximumDigitalZoom() : 1.0;
}
/*!
\property QCameraFocus::opticalZoom
\brief The current optical zoom value.
\since 1.1
\sa QCameraFocus::digitalZoom
*/
qreal QCameraFocus::opticalZoom() const
{
return d_func()->focusControl ? d_func()->focusControl->opticalZoom() : 1.0;
}
/*!
\property QCameraFocus::digitalZoom
\brief The current digital zoom value.
\since 1.1
\sa QCameraFocus::opticalZoom
*/
qreal QCameraFocus::digitalZoom() const
{
return d_func()->focusControl ? d_func()->focusControl->digitalZoom() : 1.0;
}
/*!
Set the camera \a optical and \a digital zoom values.
\since 1.1
*/
void QCameraFocus::zoomTo(qreal optical, qreal digital)
{
if (d_func()->focusControl)
d_func()->focusControl->zoomTo(optical, digital);
else
qWarning("The camera doesn't support zooming.");
}
/*!
\enum QCameraFocus::FocusMode
\value ManualFocus Manual or fixed focus mode.
\value AutoFocus One-shot auto focus mode.
\value ContinuousFocus Continuous auto focus mode.
\value InfinityFocus Focus strictly to infinity.
\value HyperfocalFocus Focus to hyperfocal distance, with with the maximum depth of field achieved.
All objects at distances from half of this
distance out to infinity will be acceptably sharp.
\value MacroFocus One shot auto focus to objects close to camera.
*/
/*!
\enum QCameraFocus::FocusPointMode
\value FocusPointAuto Automatically select one or multiple focus points.
\value FocusPointCenter Focus to the frame center.
\value FocusPointFaceDetection Focus on faces in the frame.
\value FocusPointCustom Focus to the custom point, defined by QCameraFocus::customFocusPoint property.
*/
/*!
\fn void QCameraFocus::opticalZoomChanged(qreal value)
Signal emitted when optical zoom value changes to new \a value.
\since 1.1
*/
/*!
\fn void QCameraFocus::digitalZoomChanged(qreal value)
Signal emitted when digital zoom value changes to new \a value.
\since 1.1
*/
/*!
\fn void QCameraFocus::maximumOpticalZoomChanged(qreal zoom)
Signal emitted when the maximum supported optical \a zoom value changed.
\since 1.1
*/
/*!
\fn void QCameraFocus::maximumDigitalZoomChanged(qreal zoom)
Signal emitted when the maximum supported digital \a zoom value changed.
The maximum supported zoom value can depend on other camera settings,
like capture mode or resolution.
\since 1.1
*/
/*!
\fn QCameraFocus::focusZonesChanged()
Signal is emitted when the set of zones, camera focused on is changed.
Usually the zones list is changed when the camera is focused.
\since 1.1
*/
#include "moc_qcamerafocus.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,183 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAFOCUS_H
#define QCAMERAFOCUS_H
#include <QtCore/qstringlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qsize.h>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <QtCore/qshareddata.h>
#include <qmediaobject.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QCamera;
class QCameraFocusZoneData;
class Q_MULTIMEDIA_EXPORT QCameraFocusZone {
public:
enum FocusZoneStatus {
Invalid,
Unused,
Selected,
Focused
};
QCameraFocusZone();
QCameraFocusZone(const QRectF &area, FocusZoneStatus status = Selected);
QCameraFocusZone(const QCameraFocusZone &other);
QCameraFocusZone& operator=(const QCameraFocusZone &other);
bool operator==(const QCameraFocusZone &other) const;
bool operator!=(const QCameraFocusZone &other) const;
~QCameraFocusZone();
bool isValid() const;
QRectF area() const;
FocusZoneStatus status() const;
void setStatus(FocusZoneStatus status);
private:
QSharedDataPointer<QCameraFocusZoneData> d;
};
typedef QList<QCameraFocusZone> QCameraFocusZoneList;
class QCameraFocusPrivate;
class Q_MULTIMEDIA_EXPORT QCameraFocus : public QObject
{
Q_OBJECT
Q_PROPERTY(FocusMode focusMode READ focusMode WRITE setFocusMode)
Q_PROPERTY(FocusPointMode focusPointMode READ focusPointMode WRITE setFocusPointMode)
Q_PROPERTY(QPointF customFocusPoint READ customFocusPoint WRITE setCustomFocusPoint)
Q_PROPERTY(QCameraFocusZoneList focusZones READ focusZones NOTIFY focusZonesChanged)
Q_PROPERTY(qreal opticalZoom READ opticalZoom NOTIFY opticalZoomChanged)
Q_PROPERTY(qreal digitalZoom READ digitalZoom NOTIFY digitalZoomChanged)
Q_ENUMS(FocusMode)
Q_ENUMS(FocusPointMode)
public:
enum FocusMode {
ManualFocus = 0x1,
HyperfocalFocus = 0x02,
InfinityFocus = 0x04,
AutoFocus = 0x8,
ContinuousFocus = 0x10,
MacroFocus = 0x20
};
Q_DECLARE_FLAGS(FocusModes, FocusMode)
enum FocusPointMode {
FocusPointAuto,
FocusPointCenter,
FocusPointFaceDetection,
FocusPointCustom
};
bool isAvailable() const;
FocusMode focusMode() const;
void setFocusMode(FocusMode mode);
bool isFocusModeSupported(FocusMode mode) const;
FocusPointMode focusPointMode() const;
void setFocusPointMode(FocusPointMode mode);
bool isFocusPointModeSupported(FocusPointMode) const;
QPointF customFocusPoint() const;
void setCustomFocusPoint(const QPointF &point);
QCameraFocusZoneList focusZones() const;
qreal maximumOpticalZoom() const;
qreal maximumDigitalZoom() const;
qreal opticalZoom() const;
qreal digitalZoom() const;
void zoomTo(qreal opticalZoom, qreal digitalZoom);
Q_SIGNALS:
void opticalZoomChanged(qreal);
void digitalZoomChanged(qreal);
void focusZonesChanged();
void maximumOpticalZoomChanged(qreal);
void maximumDigitalZoomChanged(qreal);
private:
friend class QCamera;
QCameraFocus(QCamera *camera);
~QCameraFocus();
Q_DISABLE_COPY(QCameraFocus)
Q_DECLARE_PRIVATE(QCameraFocus)
QCameraFocusPrivate *d_ptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraFocus::FocusModes)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCameraFocus::FocusModes)
Q_DECLARE_METATYPE(QCameraFocus::FocusPointMode)
Q_MEDIA_ENUM_DEBUG(QCameraFocus, FocusMode)
Q_MEDIA_ENUM_DEBUG(QCameraFocus, FocusPointMode)
QT_END_HEADER
#endif // QCAMERAFOCUS_H

View File

@@ -0,0 +1,253 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcamerafocuscontrol.h>
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QCameraFocusControl
\brief The QCameraFocusControl class supplies control for
focusing related camera parameters.
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.1
The interface name of QCameraFocusControl is \c com.nokia.Qt.QCameraFocusControl/1.0 as
defined in QCameraFocusControl_iid.
\sa QMediaService::requestControl(), QCamera
*/
/*!
\macro QCameraFocusControl_iid
\c com.nokia.Qt.QCameraFocusControl/1.0
Defines the interface name of the QCameraFocusControl class.
\relates QCameraFocusControl
*/
/*!
Constructs a camera control object with \a parent.
*/
QCameraFocusControl::QCameraFocusControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
Destruct the camera control object.
*/
QCameraFocusControl::~QCameraFocusControl()
{
}
/*!
\fn QCameraFocus::FocusMode QCameraFocusControl::focusMode() const
Returns the focus mode being used.
\since 1.1
*/
/*!
\fn void QCameraFocusControl::setFocusMode(QCameraFocus::FocusMode mode)
Set the focus mode to \a mode.
\since 1.1
*/
/*!
\fn bool QCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusMode mode) const
Returns true if focus \a mode is supported.
\since 1.1
*/
/*!
\fn qreal QCameraFocusControl::maximumOpticalZoom() const
Returns the maximum optical zoom value, or 1.0 if optical zoom is not supported.
\since 1.1
*/
/*!
\fn qreal QCameraFocusControl::maximumDigitalZoom() const
Returns the maximum digital zoom value, or 1.0 if digital zoom is not supported.
\since 1.1
*/
/*!
\fn qreal QCameraFocusControl::opticalZoom() const
Return the current optical zoom value.
\since 1.1
*/
/*!
\fn qreal QCameraFocusControl::digitalZoom() const
Return the current digital zoom value.
\since 1.1
*/
/*!
\fn void QCameraFocusControl::zoomTo(qreal optical, qreal digital)
Sets \a optical and \a digital zoom values.
\since 1.1
*/
/*!
\fn QCameraFocusControl::focusPointMode() const
Returns the camera focus point selection mode.
\since 1.1
*/
/*!
\fn QCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
Sets the camera focus point selection \a mode.
\since 1.1
*/
/*!
\fn QCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
Returns true if the camera focus point \a mode is supported.
\since 1.1
*/
/*!
\fn QCameraFocusControl::customFocusPoint() const
Return the position of custom focus point, in relative frame coordinates:
QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center.
Custom focus point is used only in FocusPointCustom focus mode.
\since 1.1
*/
/*!
\fn QCameraFocusControl::setCustomFocusPoint(const QPointF &point)
Sets the custom focus \a point.
If camera supports fixed set of focus points,
it should use the nearest supported focus point,
and return the actual focus point with QCameraFocusControl::focusZones().
\since 1.1
\sa QCameraFocusControl::customFocusPoint(), QCameraFocusControl::focusZones()
*/
/*!
\fn QCameraFocusControl::focusZones() const
Returns the list of zones, the camera is using for focusing or focused on.
\since 1.1
*/
/*!
\fn void QCameraFocusControl::opticalZoomChanged(qreal zoom)
Signal emitted when the optical \a zoom value changed.
\since 1.1
*/
/*!
\fn void QCameraFocusControl::digitalZoomChanged(qreal zoom)
Signal emitted when the digital \a zoom value changed.
\since 1.1
*/
/*!
\fn void QCameraFocusControl::maximumOpticalZoomChanged(qreal zoom)
Signal emitted when the maximum supported optical \a zoom value changed.
\since 1.1
*/
/*!
\fn void QCameraFocusControl::maximumDigitalZoomChanged(qreal zoom)
Signal emitted when the maximum supported digital \a zoom value changed.
The maximum supported zoom value can depend on other camera settings,
like capture mode or resolution.
\since 1.1
*/
/*!
\fn QCameraFocusControl::focusZonesChanged()
Signal is emitted when the set of zones, camera focused on is changed.
Usually the zones list is changed when the camera is focused.
\since 1.1
\sa QCameraFocusControl::focusZones()
*/
#include "moc_qcamerafocuscontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAFOCUSCONTROL_H
#define QCAMERAFOCUSCONTROL_H
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qcamerafocus.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraFocusControl : public QMediaControl
{
Q_OBJECT
public:
~QCameraFocusControl();
virtual QCameraFocus::FocusMode focusMode() const = 0;
virtual void setFocusMode(QCameraFocus::FocusMode mode) = 0;
virtual bool isFocusModeSupported(QCameraFocus::FocusMode mode) const = 0;
virtual qreal maximumOpticalZoom() const = 0;
virtual qreal maximumDigitalZoom() const = 0;
virtual qreal opticalZoom() const = 0;
virtual qreal digitalZoom() const = 0;
virtual void zoomTo(qreal optical, qreal digital) = 0;
virtual QCameraFocus::FocusPointMode focusPointMode() const = 0;
virtual void setFocusPointMode(QCameraFocus::FocusPointMode mode) = 0;
virtual bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const = 0;
virtual QPointF customFocusPoint() const = 0;
virtual void setCustomFocusPoint(const QPointF &point) = 0;
virtual QCameraFocusZoneList focusZones() const = 0;
Q_SIGNALS:
void opticalZoomChanged(qreal opticalZoom);
void digitalZoomChanged(qreal digitalZoom);
void focusZonesChanged();
void maximumOpticalZoomChanged(qreal);
void maximumDigitalZoomChanged(qreal);
protected:
QCameraFocusControl(QObject* parent = 0);
};
#define QCameraFocusControl_iid "com.nokia.Qt.QCameraFocusingControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraFocusControl, QCameraFocusControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QCAMERAFOCUSCONTROL_H

View File

@@ -0,0 +1,681 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameraimagecapture.h>
#include <qcameraimagecapturecontrol.h>
#include <qmediaencodersettings.h>
#include <qcameracapturedestinationcontrol.h>
#include <qcameracapturebufferformatcontrol.h>
#include <qimageencodercontrol.h>
#include <qmediaobject_p.h>
#include <qmediaservice.h>
#include <qcamera.h>
#include <qcameracontrol.h>
#include <QtCore/qdebug.h>
#include <QtCore/qurl.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qmetaobject.h>
QT_BEGIN_NAMESPACE
/*!
\class QCameraImageCapture
\inmodule QtMultimedia
\ingroup camera
\since 1.1
\brief The QCameraImageCapture class is used for the recording of media content.
The QCameraImageCapture class is a high level images recording class.
It's not intended to be used alone but for accessing the media
recording functions of other media objects, like QCamera.
\snippet doc/src/snippets/multimedia-snippets/camera.cpp Camera
\snippet doc/src/snippets/multimedia-snippets/camera.cpp Camera keys
\sa QCamera
*/
namespace
{
class MediaRecorderRegisterMetaTypes
{
public:
MediaRecorderRegisterMetaTypes()
{
qRegisterMetaType<QCameraImageCapture::Error>("QCameraImageCapture::Error");
qRegisterMetaType<QCameraImageCapture::CaptureDestination>("QCameraImageCapture::CaptureDestination");
qRegisterMetaType<QCameraImageCapture::CaptureDestinations>("QCameraImageCapture::CaptureDestinations");
}
} _registerRecorderMetaTypes;
}
class QCameraImageCapturePrivate
{
Q_DECLARE_NON_CONST_PUBLIC(QCameraImageCapture)
public:
QCameraImageCapturePrivate();
QMediaObject *mediaObject;
QCameraImageCaptureControl *control;
QImageEncoderControl *encoderControl;
QCameraCaptureDestinationControl *captureDestinationControl;
QCameraCaptureBufferFormatControl *bufferFormatControl;
QCameraImageCapture::Error error;
QString errorString;
void _q_error(int id, int error, const QString &errorString);
void _q_readyChanged(bool);
void _q_serviceDestroyed();
void unsetError() { error = QCameraImageCapture::NoError; errorString.clear(); }
QCameraImageCapture *q_ptr;
};
QCameraImageCapturePrivate::QCameraImageCapturePrivate():
mediaObject(0),
control(0),
encoderControl(0),
captureDestinationControl(0),
bufferFormatControl(0),
error(QCameraImageCapture::NoError)
{
}
void QCameraImageCapturePrivate::_q_error(int id, int error, const QString &errorString)
{
Q_Q(QCameraImageCapture);
this->error = QCameraImageCapture::Error(error);
this->errorString = errorString;
emit q->error(id, this->error, errorString);
}
void QCameraImageCapturePrivate::_q_readyChanged(bool ready)
{
Q_Q(QCameraImageCapture);
emit q->readyForCaptureChanged(ready);
}
void QCameraImageCapturePrivate::_q_serviceDestroyed()
{
mediaObject = 0;
control = 0;
encoderControl = 0;
captureDestinationControl = 0;
bufferFormatControl = 0;
}
/*!
Constructs a media recorder which records the media produced by \a mediaObject.
The \a parent is passed to QMediaObject.
*/
QCameraImageCapture::QCameraImageCapture(QMediaObject *mediaObject, QObject *parent):
QObject(parent), d_ptr(new QCameraImageCapturePrivate)
{
Q_D(QCameraImageCapture);
d->q_ptr = this;
if (mediaObject)
mediaObject->bind(this);
}
/*!
Destroys images capture object.
*/
QCameraImageCapture::~QCameraImageCapture()
{
Q_D(QCameraImageCapture);
if (d->mediaObject)
d->mediaObject->unbind(this);
}
/*!
\reimp
\since 1.1
*/
QMediaObject *QCameraImageCapture::mediaObject() const
{
return d_func()->mediaObject;
}
/*!
\reimp
\since 1.1
*/
bool QCameraImageCapture::setMediaObject(QMediaObject *mediaObject)
{
Q_D(QCameraImageCapture);
if (d->mediaObject) {
if (d->control) {
disconnect(d->control, SIGNAL(imageExposed(int)),
this, SIGNAL(imageExposed(int)));
disconnect(d->control, SIGNAL(imageCaptured(int,QImage)),
this, SIGNAL(imageCaptured(int,QImage)));
disconnect(d->control, SIGNAL(imageAvailable(int,QVideoFrame)),
this, SIGNAL(imageAvailable(int,QVideoFrame)));
disconnect(d->control, SIGNAL(imageMetadataAvailable(int,QtMultimedia::MetaData,QVariant)),
this, SIGNAL(imageMetadataAvailable(int,QtMultimedia::MetaData,QVariant)));
disconnect(d->control, SIGNAL(imageMetadataAvailable(int,QString,QVariant)),
this, SIGNAL(imageMetadataAvailable(int,QString,QVariant)));
disconnect(d->control, SIGNAL(imageSaved(int,QString)),
this, SIGNAL(imageSaved(int,QString)));
disconnect(d->control, SIGNAL(readyForCaptureChanged(bool)),
this, SLOT(_q_readyChanged(bool)));
disconnect(d->control, SIGNAL(error(int,int,QString)),
this, SLOT(_q_error(int,int,QString)));
if (d->captureDestinationControl) {
disconnect(d->captureDestinationControl, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)),
this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
}
if (d->bufferFormatControl) {
disconnect(d->bufferFormatControl, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)),
this, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)));
}
QMediaService *service = d->mediaObject->service();
service->releaseControl(d->control);
if (d->encoderControl)
service->releaseControl(d->encoderControl);
if (d->captureDestinationControl)
service->releaseControl(d->captureDestinationControl);
if (d->bufferFormatControl)
service->releaseControl(d->bufferFormatControl);
disconnect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
}
}
d->mediaObject = mediaObject;
if (d->mediaObject) {
QMediaService *service = mediaObject->service();
if (service) {
d->control = qobject_cast<QCameraImageCaptureControl*>(service->requestControl(QCameraImageCaptureControl_iid));
if (d->control) {
d->encoderControl = qobject_cast<QImageEncoderControl *>(service->requestControl(QImageEncoderControl_iid));
d->captureDestinationControl = qobject_cast<QCameraCaptureDestinationControl *>(
service->requestControl(QCameraCaptureDestinationControl_iid));
d->bufferFormatControl = qobject_cast<QCameraCaptureBufferFormatControl *>(
service->requestControl(QCameraCaptureBufferFormatControl_iid));
connect(d->control, SIGNAL(imageExposed(int)),
this, SIGNAL(imageExposed(int)));
connect(d->control, SIGNAL(imageCaptured(int,QImage)),
this, SIGNAL(imageCaptured(int,QImage)));
connect(d->control, SIGNAL(imageMetadataAvailable(int,QtMultimedia::MetaData,QVariant)),
this, SIGNAL(imageMetadataAvailable(int,QtMultimedia::MetaData,QVariant)));
connect(d->control, SIGNAL(imageMetadataAvailable(int,QString,QVariant)),
this, SIGNAL(imageMetadataAvailable(int,QString,QVariant)));
connect(d->control, SIGNAL(imageAvailable(int,QVideoFrame)),
this, SIGNAL(imageAvailable(int,QVideoFrame)));
connect(d->control, SIGNAL(imageSaved(int, QString)),
this, SIGNAL(imageSaved(int, QString)));
connect(d->control, SIGNAL(readyForCaptureChanged(bool)),
this, SLOT(_q_readyChanged(bool)));
connect(d->control, SIGNAL(error(int,int,QString)),
this, SLOT(_q_error(int,int,QString)));
if (d->captureDestinationControl) {
connect(d->captureDestinationControl, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)),
this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
}
if (d->bufferFormatControl) {
connect(d->bufferFormatControl, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)),
this, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)));
}
connect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
return true;
}
}
}
// without QCameraImageCaptureControl discard the media object
d->mediaObject = 0;
d->control = 0;
d->encoderControl = 0;
d->captureDestinationControl = 0;
d->bufferFormatControl = 0;
return false;
}
/*!
Returns true if the images capture service ready to use.
\since 1.1
*/
bool QCameraImageCapture::isAvailable() const
{
if (d_func()->control != NULL)
return true;
else
return false;
}
/*!
Returns the availability error code.
\since 1.1
*/
QtMultimedia::AvailabilityError QCameraImageCapture::availabilityError() const
{
if (d_func()->control != NULL)
return QtMultimedia::NoError;
else
return QtMultimedia::ServiceMissingError;
}
/*!
Returns the current error state.
\since 1.1
\sa errorString()
*/
QCameraImageCapture::Error QCameraImageCapture::error() const
{
return d_func()->error;
}
/*!
Returns a string describing the current error state.
\since 1.1
\sa error()
*/
QString QCameraImageCapture::errorString() const
{
return d_func()->errorString;
}
/*!
Returns a list of supported image codecs.
\since 1.1
*/
QStringList QCameraImageCapture::supportedImageCodecs() const
{
return d_func()->encoderControl ?
d_func()->encoderControl->supportedImageCodecs() : QStringList();
}
/*!
Returns a description of an image \a codec.
\since 1.1
*/
QString QCameraImageCapture::imageCodecDescription(const QString &codec) const
{
return d_func()->encoderControl ?
d_func()->encoderControl->imageCodecDescription(codec) : QString();
}
/*!
Returns a list of resolutions images can be encoded at.
If non null image \a settings parameter is passed,
the returned list is reduced to resolution supported with partial settings like image codec or quality applied.
If the encoder supports arbitrary resolutions within the supported range,
*\a continuous is set to true, otherwise *\a continuous is set to false.
\since 1.1
\sa QImageEncoderSettings::resolution()
*/
QList<QSize> QCameraImageCapture::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const
{
if (continuous)
*continuous = false;
return d_func()->encoderControl ?
d_func()->encoderControl->supportedResolutions(settings, continuous) : QList<QSize>();
}
/*!
Returns the image encoder settings being used.
\since 1.1
\sa setEncodingSettings()
*/
QImageEncoderSettings QCameraImageCapture::encodingSettings() const
{
return d_func()->encoderControl ?
d_func()->encoderControl->imageSettings() : QImageEncoderSettings();
}
/*!
Sets the image encoding \a settings.
If some parameters are not specified, or null settings are passed,
the encoder choose the default encoding parameters.
\since 1.1
\sa encodingSettings()
*/
void QCameraImageCapture::setEncodingSettings(const QImageEncoderSettings &settings)
{
Q_D(QCameraImageCapture);
if (d->encoderControl) {
QCamera *camera = qobject_cast<QCamera*>(d->mediaObject);
if (camera && camera->captureMode() == QCamera::CaptureStillImage) {
QMetaObject::invokeMethod(camera,
"_q_preparePropertyChange",
Qt::DirectConnection,
Q_ARG(int, QCameraControl::ImageEncodingSettings));
}
d->encoderControl->setImageSettings(settings);
}
}
/*!
Returns the list of supported buffer image capture formats.
\since 1.1
\sa bufferFormat() setBufferFormat()
*/
QList<QVideoFrame::PixelFormat> QCameraImageCapture::supportedBufferFormats() const
{
if (d_func()->bufferFormatControl)
return d_func()->bufferFormatControl->supportedBufferFormats();
else
return QList<QVideoFrame::PixelFormat>();
}
/*!
Returns the buffer image capture format being used.
\since 1.2
\sa supportedBufferCaptureFormats() setBufferCaptureFormat()
*/
QVideoFrame::PixelFormat QCameraImageCapture::bufferFormat() const
{
if (d_func()->bufferFormatControl)
return d_func()->bufferFormatControl->bufferFormat();
else
return QVideoFrame::Format_Invalid;
}
/*!
Sets the buffer image capture format to be used.
\since 1.2
\sa bufferCaptureFormat() supportedBufferCaptureFormats() captureDestination()
*/
void QCameraImageCapture::setBufferFormat(const QVideoFrame::PixelFormat format)
{
if (d_func()->bufferFormatControl)
d_func()->bufferFormatControl->setBufferFormat(format);
}
/*!
Returns true if the image capture \a destination is supported; otherwise returns false.
\since 1.2
\sa captureDestination() setCaptureDestination()
*/
bool QCameraImageCapture::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
{
if (d_func()->captureDestinationControl)
return d_func()->captureDestinationControl->isCaptureDestinationSupported(destination);
else
return destination == CaptureToFile;
}
/*!
Returns the image capture destination being used.
\since 1.2
\sa isCaptureDestinationSupported() setCaptureDestination()
*/
QCameraImageCapture::CaptureDestinations QCameraImageCapture::captureDestination() const
{
if (d_func()->captureDestinationControl)
return d_func()->captureDestinationControl->captureDestination();
else
return CaptureToFile;
}
/*!
Sets the capture \a destination to be used.
\since 1.2
\sa isCaptureDestinationSupported() captureDestination()
*/
void QCameraImageCapture::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
{
Q_D(QCameraImageCapture);
if (d->captureDestinationControl)
d->captureDestinationControl->setCaptureDestination(destination);
}
/*!
\property QCameraImageCapture::readyForCapture
Indicates the service is ready to capture a an image immediately.
\since 1.1
*/
bool QCameraImageCapture::isReadyForCapture() const
{
if (d_func()->control)
return d_func()->control->isReadyForCapture();
else
return false;
}
/*!
\fn QCameraImageCapture::readyForCaptureChanged(bool ready)
Signals that a camera's \a ready for capture state has changed.
\since 1.1
*/
/*!
Capture the image and save it to \a file.
This operation is asynchronous in majority of cases,
followed by signals QCameraImageCapture::imageCaptured(), QCameraImageCapture::imageSaved()
or QCameraImageCapture::error().
If an empty \a file is passed, the camera backend choses
the default location and naming scheme for photos on the system,
if only file name without full path is specified, the image will be saved to
the default directory, with a full path reported with imageCaptured() and imageSaved() signals.
QCameraImageCapture::capture returns the capture Id parameter, used with
imageExposed(), imageCaptured() and imageSaved() signals.
\since 1.1
*/
int QCameraImageCapture::capture(const QString &file)
{
Q_D(QCameraImageCapture);
d->unsetError();
if (d->control) {
return d->control->capture(file);
} else {
d->error = NotSupportedFeatureError;
d->errorString = tr("Device does not support images capture.");
emit error(-1, d->error, d->errorString);
}
return -1;
}
/*!
Cancel incomplete capture requests.
Already captured and queused for proicessing images may be discarded.
\since 1.1
*/
void QCameraImageCapture::cancelCapture()
{
Q_D(QCameraImageCapture);
d->unsetError();
if (d->control) {
d->control->cancelCapture();
} else {
d->error = NotSupportedFeatureError;
d->errorString = tr("Device does not support images capture.");
emit error(-1, d->error, d->errorString);
}
}
/*!
\enum QCameraImageCapture::Error
\value NoError No Errors.
\value NotReadyError The service is not ready for capture yet.
\value ResourceError Device is not ready or not available.
\value NotSupportedFeatureError Device does not support stillimages capture.
\value FormatError Current format is not supported.
\value OutOfSpaceError No space left on device.
*/
/*!
\enum QCameraImageCapture::DriveMode
\value SingleImageCapture Drive mode is capturing a single picture.
*/
/*!
\fn QCameraImageCapture::error(int id, QCameraImageCapture::Error error, const QString &errorString)
Signals that the capture request \a id has failed with an \a error
and \a errorString description.
\since 1.1
*/
/*!
\fn QCameraImageCapture::bufferFormatChanged(QVideoFrame::PixelFormat format)
Signal emitted when the buffer \a format for the buffer image capture has changed.
\since 1.2
*/
/*!
\fn QCameraImageCapture::captureDestinationChanged(CaptureDestinations destination)
Signal emitted when the capture \a destination has changed.
\since 1.2
*/
/*!
\fn QCameraImageCapture::imageExposed(int id)
Signal emitted when the frame with request \a id was exposed.
\since 1.1
*/
/*!
\fn QCameraImageCapture::imageCaptured(int id, const QImage &preview);
Signal emitted when the frame with request \a id was captured, but not processed and saved yet.
Frame \a preview can be displayed to user.
\since 1.1
*/
/*!
\fn QCameraImageCapture::imageMetadataAvailable(int id, QtMultimedia::MetaData key, const QVariant &value)
Signals that a metadata for an image with request \a id is available.
This signal is emitted for metadata \a value with a \a key listed in QtMultimedia::MetaData enum.
This signal is emitted between imageExposed and imageSaved signals.
\since 1.2
*/
/*!
\fn QCameraImageCapture::imageMetadataAvailable(int id, const QString &key, const QVariant &value)
Signals that a metadata for an image with request \a id is available.
This signal is emitted for extended metadata \a value with a \a key not listed in QtMultimedia::MetaData enum.
This signal is emitted between imageExposed and imageSaved signals.
\since 1.2
*/
/*!
\fn QCameraImageCapture::imageAvailable(int id, const QVideoFrame &buffer)
Signal emitted when the frame with request \a id is available as \a buffer.
\since 1.2
*/
/*!
\fn QCameraImageCapture::imageSaved(int id, const QString &fileName)
Signal emitted when the frame with request \a id was saved to \a fileName.
\since 1.1
*/
#include "moc_qcameraimagecapture.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,170 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAIMAGECAPTURE_H
#define QCAMERAIMAGECAPTURE_H
#include <qmediaobject.h>
#include <qmediaencodersettings.h>
#include <qmediabindableinterface.h>
#include <qvideoframe.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QSize;
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
class QImageEncoderSettings;
class QCameraImageCapturePrivate;
class Q_MULTIMEDIA_EXPORT QCameraImageCapture : public QObject, public QMediaBindableInterface
{
Q_OBJECT
Q_INTERFACES(QMediaBindableInterface)
Q_ENUMS(Error)
Q_ENUMS(CaptureDestination)
Q_PROPERTY(bool readyForCapture READ isReadyForCapture NOTIFY readyForCaptureChanged)
public:
enum Error
{
NoError,
NotReadyError,
ResourceError,
OutOfSpaceError,
NotSupportedFeatureError,
FormatError
};
enum DriveMode
{
SingleImageCapture
};
enum CaptureDestination
{
CaptureToFile = 0x01,
CaptureToBuffer = 0x02
};
Q_DECLARE_FLAGS(CaptureDestinations, CaptureDestination)
QCameraImageCapture(QMediaObject *mediaObject, QObject *parent = 0);
~QCameraImageCapture();
bool isAvailable() const;
QtMultimedia::AvailabilityError availabilityError() const;
QMediaObject *mediaObject() const;
Error error() const;
QString errorString() const;
bool isReadyForCapture() const;
QStringList supportedImageCodecs() const;
QString imageCodecDescription(const QString &codecName) const;
QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
bool *continuous = 0) const;
QImageEncoderSettings encodingSettings() const;
void setEncodingSettings(const QImageEncoderSettings& settings);
QList<QVideoFrame::PixelFormat> supportedBufferFormats() const;
QVideoFrame::PixelFormat bufferFormat() const;
void setBufferFormat(QVideoFrame::PixelFormat format);
bool isCaptureDestinationSupported(CaptureDestinations destination) const;
CaptureDestinations captureDestination() const;
void setCaptureDestination(CaptureDestinations destination);
public Q_SLOTS:
int capture(const QString &location = QString());
void cancelCapture();
Q_SIGNALS:
void error(int id, QCameraImageCapture::Error error, const QString &errorString);
void readyForCaptureChanged(bool);
void bufferFormatChanged(QVideoFrame::PixelFormat);
void captureDestinationChanged(QCameraImageCapture::CaptureDestinations);
void imageExposed(int id);
void imageCaptured(int id, const QImage &preview);
void imageMetadataAvailable(int id, QtMultimedia::MetaData key, const QVariant &value);
void imageMetadataAvailable(int id, const QString &key, const QVariant &value);
void imageAvailable(int id, const QVideoFrame &image);
void imageSaved(int id, const QString &fileName);
protected:
bool setMediaObject(QMediaObject *);
QCameraImageCapturePrivate *d_ptr;
private:
Q_DISABLE_COPY(QCameraImageCapture)
Q_DECLARE_PRIVATE(QCameraImageCapture)
Q_PRIVATE_SLOT(d_func(), void _q_error(int, int, const QString &))
Q_PRIVATE_SLOT(d_func(), void _q_readyChanged(bool))
Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed())
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraImageCapture::CaptureDestinations)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCameraImageCapture::Error)
Q_DECLARE_METATYPE(QCameraImageCapture::CaptureDestination)
Q_DECLARE_METATYPE(QCameraImageCapture::CaptureDestinations)
Q_MEDIA_ENUM_DEBUG(QCameraImageCapture, Error)
Q_MEDIA_ENUM_DEBUG(QCameraImageCapture, CaptureDestination)
QT_END_HEADER
#endif

View File

@@ -0,0 +1,208 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameraimagecapturecontrol.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
/*!
\class QCameraImageCaptureControl
\brief The QCameraImageCaptureControl class provides a control interface
for image capture services.
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.1
The interface name of QCameraImageCaptureControl is \c com.nokia.Qt.QCameraImageCaptureControl/1.0 as
defined in QCameraImageCaptureControl_iid.
\sa QMediaService::requestControl()
*/
/*!
\macro QCameraImageCaptureControl_iid
\c com.nokia.Qt.QCameraImageCaptureControl/1.0
Defines the interface name of the QCameraImageCaptureControl class.
\relates QCameraImageCaptureControl
*/
/*!
Constructs a new image capture control object with the given \a parent
*/
QCameraImageCaptureControl::QCameraImageCaptureControl(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys an image capture control.
*/
QCameraImageCaptureControl::~QCameraImageCaptureControl()
{
}
/*!
\fn QCameraImageCaptureControl::isReadyForCapture() const
Identifies if a capture control is ready to perform a capture
immediately (all the resources necessary for image capture are allocated,
hardware initialized, flash is charged, etc).
Returns true if the camera is ready for capture; and false if it is not.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::readyForCaptureChanged(bool ready)
Signals that a capture control's \a ready state has changed.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::capture(const QString &fileName)
Initiates the capture of an image to \a fileName.
The \a fileName can be relative or empty,
in this case the service should use the system specific place
and file naming scheme.
Returns the capture request id number, which is used later
with imageExposed(), imageCaptured() and imageSaved() signals.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::cancelCapture()
Cancel pending capture requests.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::imageExposed(int requestId)
Signals that an image with it \a requestId
has just been exposed.
This signal can be used for the shutter sound or other indicaton.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::imageCaptured(int requestId, const QImage &preview)
Signals that an image with it \a requestId
has been captured and a \a preview is available.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::imageMetadataAvailable(int id, QtMultimedia::MetaData key, const QVariant &value)
Signals that a metadata for an image with request \a id is available.
This signal is emitted for metadata \a value with a \a key listed in QtMultimedia::MetaData enum.
This signal should be emitted between imageExposed and imageSaved signals.
\since 1.2
*/
/*!
\fn QCameraImageCaptureControl::imageMetadataAvailable(int id, const QString &key, const QVariant &value)
Signals that a metadata for an image with request \a id is available.
This signal is emitted for extended metadata \a value with a \a key not listed in QtMultimedia::MetaData enum.
This signal should be emitted between imageExposed and imageSaved signals.
\since 1.2
*/
/*!
\fn QCameraImageCaptureControl::imageAvailable(int requestId, const QVideoFrame &buffer)
Signals that a captured \a buffer with a \a requestId is available.
\since 1.2
*/
/*!
\fn QCameraImageCaptureControl::imageSaved(int requestId, const QString &fileName)
Signals that a captured image with a \a requestId has been saved
to \a fileName.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::driveMode() const
Returns the current camera drive mode.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
Sets the current camera drive \a mode.
\since 1.1
*/
/*!
\fn QCameraImageCaptureControl::error(int id, int error, const QString &errorString)
Signals the capture request \a id failed with \a error code and message \a errorString.
\since 1.1
\sa QCameraImageCapture::Error
*/
#include "moc_qcameraimagecapturecontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAIMAGECAPTURECONTROL_H
#define QCAMERAIMAGECAPTURECONTROL_H
#include <qmediacontrol.h>
#include <qcameraimagecapture.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QImage;
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
class Q_MULTIMEDIA_EXPORT QCameraImageCaptureControl : public QMediaControl
{
Q_OBJECT
public:
~QCameraImageCaptureControl();
virtual bool isReadyForCapture() const = 0;
virtual QCameraImageCapture::DriveMode driveMode() const = 0;
virtual void setDriveMode(QCameraImageCapture::DriveMode mode) = 0;
virtual int capture(const QString &fileName) = 0;
virtual void cancelCapture() = 0;
Q_SIGNALS:
void readyForCaptureChanged(bool);
void imageExposed(int id);
void imageCaptured(int id, const QImage &preview);
void imageMetadataAvailable(int id, QtMultimedia::MetaData key, const QVariant &value);
void imageMetadataAvailable(int id, const QString &key, const QVariant &value);
void imageAvailable(int id, const QVideoFrame &buffer);
void imageSaved(int id, const QString &fileName);
void error(int id, int error, const QString &errorString);
protected:
QCameraImageCaptureControl(QObject* parent = 0);
};
#define QCameraImageCaptureControl_iid "com.nokia.Qt.QCameraImageCaptureControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraImageCaptureControl, QCameraImageCaptureControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QCAMERAIMAGECAPTURECONTROL_H

View File

@@ -0,0 +1,352 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <QDebug>
#include <qcameraimageprocessing.h>
#include <qmediaobject_p.h>
#include <qcameracontrol.h>
#include <qcameraexposurecontrol.h>
#include <qcamerafocuscontrol.h>
#include <qmediarecordercontrol.h>
#include <qcameraimageprocessingcontrol.h>
#include <qcameraimagecapturecontrol.h>
#include <qvideodevicecontrol.h>
QT_BEGIN_NAMESPACE
/*!
\class QCameraImageProcessing
\brief The QCameraImageProcessing class provides interface for
focus and zoom related camera settings.
\inmodule QtMultimedia
\ingroup camera
\since 1.1
*/
class QCameraImageProcessingPrivate : public QMediaObjectPrivate
{
Q_DECLARE_NON_CONST_PUBLIC(QCameraImageProcessing)
public:
void initControls();
QCameraImageProcessing *q_ptr;
QCamera *camera;
QCameraImageProcessingControl *imageControl;
};
void QCameraImageProcessingPrivate::initControls()
{
imageControl = 0;
QMediaService *service = camera->service();
if (service)
imageControl = qobject_cast<QCameraImageProcessingControl *>(service->requestControl(QCameraImageProcessingControl_iid));
}
/*!
Construct a QCameraImageProcessing for \a camera.
*/
QCameraImageProcessing::QCameraImageProcessing(QCamera *camera):
QObject(camera), d_ptr(new QCameraImageProcessingPrivate)
{
Q_D(QCameraImageProcessing);
d->camera = camera;
d->q_ptr = this;
d->initControls();
}
/*!
Destroys the camera focus object.
*/
QCameraImageProcessing::~QCameraImageProcessing()
{
}
/*!
Returns true if image processing related settings are supported by this camera.
\since 1.1
*/
bool QCameraImageProcessing::isAvailable() const
{
return d_func()->imageControl != 0;
}
/*!
Returns the white balance mode being used.
\since 1.1
*/
QCameraImageProcessing::WhiteBalanceMode QCameraImageProcessing::whiteBalanceMode() const
{
return d_func()->imageControl ? d_func()->imageControl->whiteBalanceMode() : QCameraImageProcessing::WhiteBalanceAuto;
}
/*!
Sets the white balance to \a mode.
\since 1.1
*/
void QCameraImageProcessing::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
{
if (d_func()->imageControl)
d_func()->imageControl->setWhiteBalanceMode(mode);
}
/*!
Returns true if the white balance \a mode is supported.
\since 1.1
*/
bool QCameraImageProcessing::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
{
return d_func()->imageControl ? d_func()->imageControl->isWhiteBalanceModeSupported(mode) : false;
}
/*!
Returns the current color temperature if the
manual white balance is active, otherwise the
return value is undefined.
\since 1.1
*/
int QCameraImageProcessing::manualWhiteBalance() const
{
QVariant value;
if (d_func()->imageControl)
value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::ColorTemperature);
return value.toInt();
}
/*!
Sets manual white balance to \a colorTemperature
\since 1.1
*/
void QCameraImageProcessing::setManualWhiteBalance(int colorTemperature)
{
if (d_func()->imageControl) {
d_func()->imageControl->setProcessingParameter(
QCameraImageProcessingControl::ColorTemperature,
QVariant(colorTemperature));
}
}
/*!
Return the contrast.
\since 1.1
*/
int QCameraImageProcessing::contrast() const
{
QVariant value;
if (d_func()->imageControl)
value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Contrast);
return value.toInt();
}
/*!
Set the contrast to \a value.
Valid contrast values range between -100 and 100, the default is 0.
\since 1.1
*/
void QCameraImageProcessing::setContrast(int value)
{
if (d_func()->imageControl)
d_func()->imageControl->setProcessingParameter(QCameraImageProcessingControl::Contrast,
QVariant(value));
}
/*!
Returns the saturation value.
\since 1.1
*/
int QCameraImageProcessing::saturation() const
{
QVariant value;
if (d_func()->imageControl)
value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Saturation);
return value.toInt();
}
/*!
Sets the saturation value to \a value.
Valid saturation values range between -100 and 100, the default is 0.
\since 1.1
*/
void QCameraImageProcessing::setSaturation(int value)
{
if (d_func()->imageControl)
d_func()->imageControl->setProcessingParameter(QCameraImageProcessingControl::Saturation,
QVariant(value));
}
/*!
Identifies if sharpening is supported.
Returns true if sharpening is supported; and false if it is not.
\since 1.1
*/
bool QCameraImageProcessing::isSharpeningSupported() const
{
if (d_func()->imageControl)
return d_func()->imageControl->isProcessingParameterSupported(QCameraImageProcessingControl::Sharpening);
else
return false;
}
/*!
Returns the sharpening level.
\since 1.1
*/
int QCameraImageProcessing::sharpeningLevel() const
{
QVariant value;
if (d_func()->imageControl)
value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Sharpening);
if (value.isNull())
return -1;
else
return value.toInt();
}
/*!
Sets the sharpening \a level.
Valid sharpening level values range between -1 for default sharpening level,
0 for sharpening disabled and 100 for maximum sharpening applied.
\since 1.1
*/
void QCameraImageProcessing::setSharpeningLevel(int level)
{
Q_D(QCameraImageProcessing);
if (d->imageControl)
d->imageControl->setProcessingParameter(QCameraImageProcessingControl::Sharpening,
level == -1 ? QVariant() : QVariant(level));
}
/*!
Returns true if denoising is supported.
\since 1.1
*/
bool QCameraImageProcessing::isDenoisingSupported() const
{
if (d_func()->imageControl)
return d_func()->imageControl->isProcessingParameterSupported(QCameraImageProcessingControl::Denoising);
else
return false;
}
/*!
Returns the denoising level.
\since 1.1
*/
int QCameraImageProcessing::denoisingLevel() const
{
QVariant value;
if (d_func()->imageControl)
value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Denoising);
if (value.isNull())
return -1;
else
return value.toInt();
}
/*!
Sets the denoising \a level.
Valid denoising level values range between -1 for default denoising level,
0 for denoising disabled and 100 for maximum denoising applied.
\since 1.1
*/
void QCameraImageProcessing::setDenoisingLevel(int level)
{
Q_D(QCameraImageProcessing);
if (d->imageControl)
d->imageControl->setProcessingParameter(QCameraImageProcessingControl::Denoising,
level == -1 ? QVariant() : QVariant(level));
}
/*!
\enum QCameraImageProcessing::WhiteBalanceMode
\value WhiteBalanceManual Manual white balance. In this mode the white balance should be set with
setManualWhiteBalance()
\value WhiteBalanceAuto Auto white balance mode.
\value WhiteBalanceSunlight Sunlight white balance mode.
\value WhiteBalanceCloudy Cloudy white balance mode.
\value WhiteBalanceShade Shade white balance mode.
\value WhiteBalanceTungsten Tungsten white balance mode.
\value WhiteBalanceFluorescent Fluorescent white balance mode.
\value WhiteBalanceFlash Flash white balance mode.
\value WhiteBalanceSunset Sunset white balance mode.
\value WhiteBalanceVendor Vendor defined white balance mode.
*/
#include "moc_qcameraimageprocessing.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,124 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAIMAGEPROCESSING_H
#define QCAMERAIMAGEPROCESSING_H
#include <QtCore/qstringlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qsize.h>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qmediaservice.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QCamera;
class QCameraImageProcessingPrivate;
class Q_MULTIMEDIA_EXPORT QCameraImageProcessing : public QObject
{
Q_OBJECT
Q_ENUMS(WhiteBalanceMode)
public:
enum WhiteBalanceMode {
WhiteBalanceAuto = 0,
WhiteBalanceManual = 1,
WhiteBalanceSunlight = 2,
WhiteBalanceCloudy = 3,
WhiteBalanceShade = 4,
WhiteBalanceTungsten = 5,
WhiteBalanceFluorescent = 6,
WhiteBalanceFlash = 7,
WhiteBalanceSunset = 8,
WhiteBalanceVendor = 1000
};
bool isAvailable() const;
WhiteBalanceMode whiteBalanceMode() const;
void setWhiteBalanceMode(WhiteBalanceMode mode);
bool isWhiteBalanceModeSupported(WhiteBalanceMode mode) const;
int manualWhiteBalance() const;
void setManualWhiteBalance(int colorTemperature);
int contrast() const;
void setContrast(int value);
int saturation() const;
void setSaturation(int value);
bool isSharpeningSupported() const;
int sharpeningLevel() const;
void setSharpeningLevel(int value);
bool isDenoisingSupported() const;
int denoisingLevel() const;
void setDenoisingLevel(int value);
private:
friend class QCamera;
QCameraImageProcessing(QCamera *camera);
~QCameraImageProcessing();
Q_DISABLE_COPY(QCameraImageProcessing)
Q_DECLARE_PRIVATE(QCameraImageProcessing)
QCameraImageProcessingPrivate *d_ptr;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCameraImageProcessing::WhiteBalanceMode)
Q_MEDIA_ENUM_DEBUG(QCameraImageProcessing, WhiteBalanceMode)
QT_END_HEADER
#endif // QCAMERAIMAGEPROCESSING_H

View File

@@ -0,0 +1,169 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameraimageprocessingcontrol.h>
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QCameraImageProcessingControl
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.1
\brief The QCameraImageProcessingControl class provides an abstract class
for controlling image processing parameters, like white balance,
contrast, saturation, sharpening and denoising.
The interface name of QCameraImageProcessingControl is \c com.nokia.Qt.QCameraImageProcessingControl/1.0 as
defined in QCameraImageProcessingControl_iid.
\sa QMediaService::requestControl(), QCamera
*/
/*!
\macro QCameraImageProcessingControl_iid
\c com.nokia.Qt.QCameraImageProcessingControl/1.0
Defines the interface name of the QCameraImageProcessingControl class.
\relates QCameraImageProcessingControl
*/
/*!
Constructs an image processing control object with \a parent.
*/
QCameraImageProcessingControl::QCameraImageProcessingControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
Destruct the image processing control object.
*/
QCameraImageProcessingControl::~QCameraImageProcessingControl()
{
}
/*!
\fn QCameraImageProcessingControl::whiteBalanceMode() const
Return the white balance mode being used.
\since 1.1
*/
/*!
\fn QCameraImageProcessingControl::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
Set the white balance mode to \a mode
\since 1.1
*/
/*!
\fn QCameraImageProcessingControl::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
Returns true if the white balance \a mode is supported.
The backend should support at least QCameraImageProcessing::WhiteBalanceAuto mode.
\since 1.1
*/
/*!
\fn bool QCameraImageProcessingControl::isProcessingParameterSupported(ProcessingParameter parameter) const
Returns true if the camera supports adjusting image processing \a parameter.
Usually the the supported settings is static,
but some parameter may not be available depending on other
camera settings, like presets.
In such case the currently supported parameters should be returned.
\since 1.1
*/
/*!
\fn QCameraImageProcessingControl::processingParameter(ProcessingParameter parameter) const
Returns the image processing \a parameter value.
\since 1.1
*/
/*!
\fn QCameraImageProcessingControl::setProcessingParameter(ProcessingParameter parameter, QVariant value)
Sets the image processing \a parameter \a value.
Passing the null or invalid QVariant value allows
backend to choose the suitable parameter value.
The valid values range depends on the parameter type,
for contrast, saturation and brightness value should be
between -100 and 100, the default is 0,
For sharpening and denoising the range is 0..100,
0 for sharpening or denoising disabled
and 100 for maximum sharpening/denoising applied.
\since 1.1
*/
/*!
\enum QCameraImageProcessingControl::ProcessingParameter
\value Contrast
Image contrast.
\value Saturation
Image saturation.
\value Brightness
Image brightness.
\value Sharpening
Amount of sharpening applied.
\value Denoising
Amount of denoising applied.
\value ColorTemperature
Color temperature in K. This value is used when the manual white balance mode is selected.
\value ExtendedParameter
The base value for platform specific extended parameters.
*/
#include "moc_qcameraimageprocessingcontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,100 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERAIMAGEPROCESSINGCONTROL_H
#define QCAMERAIMAGEPROCESSINGCONTROL_H
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qcamera.h>
#include <qmediaenumdebug.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraImageProcessingControl : public QMediaControl
{
Q_OBJECT
Q_ENUMS(ProcessingParameter)
public:
~QCameraImageProcessingControl();
enum ProcessingParameter {
Contrast = 0,
Saturation = 1,
Brightness = 2,
Sharpening = 3,
Denoising = 4,
ColorTemperature = 5,
ExtendedParameter = 1000
};
virtual QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const = 0;
virtual void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode) = 0;
virtual bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode) const = 0;
virtual bool isProcessingParameterSupported(ProcessingParameter) const = 0;
virtual QVariant processingParameter(ProcessingParameter parameter) const = 0;
virtual void setProcessingParameter(ProcessingParameter parameter, QVariant value) = 0;
protected:
QCameraImageProcessingControl(QObject* parent = 0);
};
#define QCameraImageProcessingControl_iid "com.nokia.Qt.QCameraImageProcessingControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraImageProcessingControl, QCameraImageProcessingControl_iid)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QCameraImageProcessingControl::ProcessingParameter)
Q_MEDIA_ENUM_DEBUG(QCameraImageProcessingControl, ProcessingParameter)
QT_END_HEADER
#endif

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qcameralockscontrol.h>
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QCameraLocksControl
\brief The QCameraLocksControl class is an abstract base class for
classes that control still cameras or video cameras.
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.1
This service is provided by a QMediaService object via
QMediaService::control(). It is used by QCamera.
The interface name of QCameraLocksControl is \c com.nokia.Qt.QCameraLocksControl/1.0 as
defined in QCameraLocksControl_iid.
\sa QMediaService::requestControl(), QCamera
*/
/*!
\macro QCameraLocksControl_iid
\c com.nokia.Qt.QCameraLocksControl/1.0
Defines the interface name of the QCameraLocksControl class.
\relates QCameraLocksControl
*/
/*!
Constructs a camera locks control object with \a parent.
*/
QCameraLocksControl::QCameraLocksControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
Destruct the camera locks control object.
*/
QCameraLocksControl::~QCameraLocksControl()
{
}
/*!
\fn QCameraLocksControl::supportedLocks() const
Returns the lock types, the camera supports.
\since 1.1
*/
/*!
\fn QCameraLocksControl::lockStatus(QCamera::LockType lock) const
Returns the camera \a lock status.
\since 1.1
*/
/*!
\fn QCameraLocksControl::searchAndLock(QCamera::LockTypes locks)
Request camera \a locks.
\since 1.1
*/
/*!
\fn QCameraLocksControl::unlock(QCamera::LockTypes locks)
Unlock camera \a locks.
\since 1.1
*/
/*!
\fn QCameraLocksControl::lockStatusChanged(QCamera::LockType lock, QCamera::LockStatus status, QCamera::LockChangeReason reason)
Signals the \a lock \a status was changed with a specified \a reason.
\since 1.1
*/
#include "moc_qcameralockscontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QCAMERALOCKSCONTROL_H
#define QCAMERALOCKSCONTROL_H
#include <qmediacontrol.h>
#include <qmediaobject.h>
#include <qcamera.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QCameraLocksControl : public QMediaControl
{
Q_OBJECT
public:
~QCameraLocksControl();
virtual QCamera::LockTypes supportedLocks() const = 0;
virtual QCamera::LockStatus lockStatus(QCamera::LockType lock) const = 0;
virtual void searchAndLock(QCamera::LockTypes locks) = 0;
virtual void unlock(QCamera::LockTypes locks) = 0;
Q_SIGNALS:
void lockStatusChanged(QCamera::LockType type, QCamera::LockStatus status, QCamera::LockChangeReason reason);
protected:
QCameraLocksControl(QObject* parent = 0);
};
#define QCameraLocksControl_iid "com.nokia.Qt.QCameraLocksControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QCameraLocksControl, QCameraLocksControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QCAMERALOCKSCONTROL_H

View File

@@ -0,0 +1,142 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qimageencodercontrol.h"
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
/*!
\class QImageEncoderControl
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.0
\brief The QImageEncoderControl class provides access to the settings of a media service that
performs image encoding.
If a QMediaService supports encoding image data it will implement QImageEncoderControl.
This control allows to \l {setImageSettings()}{set image encoding settings} and
provides functions for quering supported image \l {supportedImageCodecs()}{codecs} and
\l {supportedResolutions()}{resolutions}.
The interface name of QImageEncoderControl is \c com.nokia.Qt.QImageEncoderControl/1.0 as
defined in QImageEncoderControl_iid.
\sa QImageEncoderSettings, QMediaService::requestControl()
*/
/*!
\macro QImageEncoderControl_iid
\c com.nokia.Qt.QImageEncoderControl/1.0
Defines the interface name of the QImageEncoderControl class.
\relates QImageEncoderControl
*/
/*!
Constructs a new image encoder control object with the given \a parent
*/
QImageEncoderControl::QImageEncoderControl(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys the image encoder control.
*/
QImageEncoderControl::~QImageEncoderControl()
{
}
/*!
\fn QImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
bool *continuous = 0) const
Returns a list of supported resolutions.
If non null image \a settings parameter is passed,
the returned list is reduced to resolutions supported with partial settings applied.
It can be used to query the list of resolutions, supported by specific image codec.
If the encoder supports arbitrary resolutions within the supported resolutions range,
*\a continuous is set to true, otherwise *\a continuous is set to false.
\since 1.0
*/
/*!
\fn QImageEncoderControl::supportedImageCodecs() const
Returns a list of supported image codecs.
\since 1.0
*/
/*!
\fn QImageEncoderControl::imageCodecDescription(const QString &codec) const
Returns a description of an image \a codec.
\since 1.0
*/
/*!
\fn QImageEncoderControl::imageSettings() const
Returns the currently used image encoder settings.
The returned value may be different tha passed to QImageEncoderControl::setImageSettings()
if the settings contains the default or undefined parameters.
In this case if the undefined parameters are already resolved, they should be returned.
\since 1.0
*/
/*!
\fn QImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
Sets the selected image encoder \a settings.
\since 1.0
*/
#include "moc_qimageencodercontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QIMAGEENCODERCONTROL_H
#define QIMAGEENCODERCONTROL_H
#include "qmediacontrol.h"
#include "qmediarecorder.h"
#include "qmediaencodersettings.h"
#include <QtCore/qsize.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QByteArray;
class QStringList;
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
class Q_MULTIMEDIA_EXPORT QImageEncoderControl : public QMediaControl
{
Q_OBJECT
public:
virtual ~QImageEncoderControl();
virtual QStringList supportedImageCodecs() const = 0;
virtual QString imageCodecDescription(const QString &codecName) const = 0;
virtual QList<QSize> supportedResolutions(const QImageEncoderSettings &settings,
bool *continuous = 0) const = 0;
virtual QImageEncoderSettings imageSettings() const = 0;
virtual void setImageSettings(const QImageEncoderSettings &settings) = 0;
protected:
QImageEncoderControl(QObject *parent = 0);
};
#define QImageEncoderControl_iid "com.nokia.Qt.QImageEncoderControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QImageEncoderControl, QImageEncoderControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,194 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qlocalmediaplaylistprovider.h"
#include "qmediaplaylistprovider_p.h"
#include "qmediacontent.h"
QT_BEGIN_NAMESPACE
class QLocalMediaPlaylistProviderPrivate: public QMediaPlaylistProviderPrivate
{
public:
QList<QMediaContent> resources;
};
QLocalMediaPlaylistProvider::QLocalMediaPlaylistProvider(QObject *parent)
:QMediaPlaylistProvider(*new QLocalMediaPlaylistProviderPrivate, parent)
{
}
QLocalMediaPlaylistProvider::~QLocalMediaPlaylistProvider()
{
}
bool QLocalMediaPlaylistProvider::isReadOnly() const
{
return false;
}
int QLocalMediaPlaylistProvider::mediaCount() const
{
return d_func()->resources.size();
}
QMediaContent QLocalMediaPlaylistProvider::media(int pos) const
{
return d_func()->resources.value(pos);
}
bool QLocalMediaPlaylistProvider::addMedia(const QMediaContent &content)
{
Q_D(QLocalMediaPlaylistProvider);
int pos = d->resources.count();
emit mediaAboutToBeInserted(pos, pos);
d->resources.append(content);
emit mediaInserted(pos, pos);
return true;
}
bool QLocalMediaPlaylistProvider::addMedia(const QList<QMediaContent> &items)
{
Q_D(QLocalMediaPlaylistProvider);
if (items.isEmpty())
return true;
int pos = d->resources.count();
int end = pos+items.count()-1;
emit mediaAboutToBeInserted(pos, end);
d->resources.append(items);
emit mediaInserted(pos, end);
return true;
}
bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QMediaContent &content)
{
Q_D(QLocalMediaPlaylistProvider);
emit mediaAboutToBeInserted(pos, pos);
d->resources.insert(pos, content);
emit mediaInserted(pos,pos);
return true;
}
bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QList<QMediaContent> &items)
{
Q_D(QLocalMediaPlaylistProvider);
if (items.isEmpty())
return true;
const int last = pos+items.count()-1;
emit mediaAboutToBeInserted(pos, last);
for (int i=0; i<items.count(); i++)
d->resources.insert(pos+i, items.at(i));
emit mediaInserted(pos, last);
return true;
}
bool QLocalMediaPlaylistProvider::removeMedia(int fromPos, int toPos)
{
Q_D(QLocalMediaPlaylistProvider);
Q_ASSERT(fromPos >= 0);
Q_ASSERT(fromPos <= toPos);
Q_ASSERT(toPos < mediaCount());
emit mediaAboutToBeRemoved(fromPos, toPos);
d->resources.erase(d->resources.begin()+fromPos, d->resources.begin()+toPos+1);
emit mediaRemoved(fromPos, toPos);
return true;
}
bool QLocalMediaPlaylistProvider::removeMedia(int pos)
{
Q_D(QLocalMediaPlaylistProvider);
emit mediaAboutToBeRemoved(pos, pos);
d->resources.removeAt(pos);
emit mediaRemoved(pos, pos);
return true;
}
bool QLocalMediaPlaylistProvider::clear()
{
Q_D(QLocalMediaPlaylistProvider);
if (!d->resources.isEmpty()) {
int lastPos = mediaCount()-1;
emit mediaAboutToBeRemoved(0, lastPos);
d->resources.clear();
emit mediaRemoved(0, lastPos);
}
return true;
}
void QLocalMediaPlaylistProvider::shuffle()
{
Q_D(QLocalMediaPlaylistProvider);
if (!d->resources.isEmpty()) {
QList<QMediaContent> resources;
while (!d->resources.isEmpty()) {
resources.append(d->resources.takeAt(qrand() % d->resources.size()));
}
d->resources = resources;
emit mediaChanged(0, mediaCount()-1);
}
}
#include "moc_qlocalmediaplaylistprovider.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QLOCALMEDIAPAYLISTPROVIDER_H
#define QLOCALMEDIAPAYLISTPROVIDER_H
#include "qmediaplaylistprovider.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QLocalMediaPlaylistProviderPrivate;
class Q_MULTIMEDIA_EXPORT QLocalMediaPlaylistProvider : public QMediaPlaylistProvider
{
Q_OBJECT
public:
QLocalMediaPlaylistProvider(QObject *parent=0);
virtual ~QLocalMediaPlaylistProvider();
virtual int mediaCount() const;
virtual QMediaContent media(int pos) const;
virtual bool isReadOnly() const;
virtual bool addMedia(const QMediaContent &content);
virtual bool addMedia(const QList<QMediaContent> &items);
virtual bool insertMedia(int pos, const QMediaContent &content);
virtual bool insertMedia(int pos, const QList<QMediaContent> &items);
virtual bool removeMedia(int pos);
virtual bool removeMedia(int start, int end);
virtual bool clear();
public Q_SLOTS:
virtual void shuffle();
private:
Q_DECLARE_PRIVATE(QLocalMediaPlaylistProvider)
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QLOCALMEDIAPAYLISTSOURCE_H

View File

@@ -0,0 +1,149 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qmediabackgroundplaybackcontrol.h"
#include "qmediacontrol_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QMediaBackgroundPlaybackControl
\inmodule QtMultimedia
\ingroup multimedia
\since 5.0
\brief The QMediaBackgroundPlaybackControl class provides access to the background playback
related control of a QMediaService.
If a QMediaService can play media in background, it should implement QMediaBackgroundPlaybackControl.
This control provides a means to set the \l {setContextId()}{contextId} for application,
\l {acquire()}{acquire the resource for playback} and \l {release()} {release the playback resource}.
The interface name of QMediaBackgroundPlaybackControl is \c com.nokia.Qt.QMediaBackgroundPlaybackControl/1.0 as
defined in QMediaBackgroundPlaybackControl_iid.
\sa QMediaService::requestControl(), QMediaPlayer
*/
/*!
\macro QMediaBackgroundPlaybackControl_iid
\c com.nokia.Qt.QMediaBackgroundPlaybackControl/1.0
Defines the interface name of the QMediaBackgroundPlaybackControl class.
\relates QMediaBackgroundPlaybackControl
*/
/*!
Destroys a media background playback control.
*/
QMediaBackgroundPlaybackControl::~QMediaBackgroundPlaybackControl()
{
}
/*!
Constructs a new media background playback control with the given \a parent.
*/
QMediaBackgroundPlaybackControl::QMediaBackgroundPlaybackControl(QObject *parent):
QMediaControl(*new QMediaControlPrivate, parent)
{
}
/*!
\fn QMediaBackgroundPlaybackControl::setContextId(const QString& contextId)
Sets the contextId for the application, the last contextId will be released if previously set.
\l {acquire()}{acquire method} will be automatically invoked after setting a new contextId.
contextId is an unique string set by the application and is used by the background daemon to
distinguish and manage different context for different application.
\since 1.0
*/
/*!
\fn QMediaBackgroundPlaybackControl::acquire()
Try to acquire the playback resource for current application
\since 1.0
*/
/*!
\fn QMediaBackgroundPlaybackControl::release()
Give up the playback resource if current applicaiton holds it.
\since 1.0
*/
/*!
\property QMediaBackgroundPlaybackControl::isAcquired()
\brief indicate whether the background playback resource is granted or not
It may take sometime for the backend to actually update this value before the first use.
By default this property is false
\since 1.0
*/
/*!
\fn QMediaBackgroundPlaybackControl::acquired()
Signals that the playback resource is acquired
\since 1.0
*/
/*!
\fn QMediaBackgroundPlaybackControl::lost()
Signals that the playback resource is lost
\since 1.0
*/
#include "moc_qmediabackgroundplaybackcontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QMEDIABACKGROUNDPLAYBACKCONTROL_H
#define QMEDIABACKGROUNDPLAYBACKCONTROL_H
#include "qmediacontrol.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QMediaBackgroundPlaybackControl : public QMediaControl
{
Q_OBJECT
public:
virtual ~QMediaBackgroundPlaybackControl();
virtual void setContextId(const QString& contextId) = 0;
virtual void acquire() = 0;
virtual void release() = 0;
virtual bool isAcquired() const = 0;
Q_SIGNALS:
void acquired();
void lost();
protected:
QMediaBackgroundPlaybackControl(QObject* parent = 0);
};
#define QMediaBackgroundPlaybackControl_iid "com.nokia.Qt.QMediaBackgroundPlaybackControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QMediaBackgroundPlaybackControl, QMediaBackgroundPlaybackControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QMEDIABACKGROUNDPLAYBACKCONTROL_H

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <qmediabindableinterface.h>
QT_BEGIN_NAMESPACE
/*!
\class QMediaBindableInterface
\inmodule QtMultimedia
\ingroup multimedia
\since 1.0
\brief The QMediaBindableInterface class is the base class for objects extending media objects functionality.
\sa
*/
/*!
Destroys a media helper object.
*/
QMediaBindableInterface::~QMediaBindableInterface()
{
}
/*!
\fn QMediaBindableInterface::mediaObject() const;
Return the currently attached media object.
\since 1.0
*/
/*!
\fn QMediaBindableInterface::setMediaObject(QMediaObject *object);
Attaches to the media \a object.
Returns true if attached successfully, otherwise returns false.
\since 1.0
*/
QT_END_NAMESPACE

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QMEDIABINDABLEINTERFACE_H
#define QMEDIABINDABLEINTERFACE_H
#include <qmediaobject.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QMediaObject;
class Q_MULTIMEDIA_EXPORT QMediaBindableInterface
{
public:
virtual ~QMediaBindableInterface();
virtual QMediaObject *mediaObject() const = 0;
protected:
friend class QMediaObject;
virtual bool setMediaObject(QMediaObject *object) = 0;
};
#define QMediaBindableInterface_iid \
"com.nokia.Qt.QMediaBindableInterface/1.0"
Q_DECLARE_INTERFACE(QMediaBindableInterface, QMediaBindableInterface_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QMEDIABINDABLEINTERFACE_H

View File

@@ -0,0 +1,126 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 "qmediacontainercontrol.h"
QT_BEGIN_NAMESPACE
/*!
\class QMediaContainerControl
\brief The QMediaContainerControl class provides access to the output container format of a QMediaService
\inmodule QtMultimedia
\ingroup multimedia-serv
\since 1.0
If a QMediaService supports writing encoded data it will implement
QMediaContainerControl. This control provides information about the output
containers supported by a media service and allows one to be selected as
the current output containers.
The functionality provided by this control is exposed to application code
through the QMediaRecorder class.
The interface name of QMediaContainerControl is \c com.nokia.Qt.QMediaContainerControl/1.0 as
defined in QMediaContainerControl_iid.
\sa QMediaService::requestControl(), QMediaRecorder
*/
/*!
\macro QMediaContainerControl_iid
\c com.nokia.Qt.QMediaContainerControl/1.0
Defines the interface name of the QMediaContainerControl class.
\relates QMediaContainerControl
*/
/*!
Constructs a new media container control with the given \a parent.
*/
QMediaContainerControl::QMediaContainerControl(QObject *parent)
:QMediaControl(parent)
{
}
/*!
Destroys a media container control.
*/
QMediaContainerControl::~QMediaContainerControl()
{
}
/*!
\fn QMediaContainerControl::supportedContainers() const
Returns a list of MIME types of supported container formats.
\since 1.0
*/
/*!
\fn QMediaContainerControl::containerMimeType() const
Returns the MIME type of the selected container format.
\since 1.0
*/
/*!
\fn QMediaContainerControl::setContainerMimeType(const QString &mimeType)
Sets the current container format to the format identified by the given \a mimeType.
\since 1.0
*/
/*!
\fn QMediaContainerControl::containerDescription(const QString &mimeType) const
Returns a description of the container format identified by the given \a mimeType.
\since 1.0
*/
#include "moc_qmediacontainercontrol.cpp"
QT_END_NAMESPACE

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QMEDIACONTAINERCONTROL_H
#define QMEDIACONTAINERCONTROL_H
#include "qmediacontrol.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class Q_MULTIMEDIA_EXPORT QMediaContainerControl : public QMediaControl
{
Q_OBJECT
public:
virtual ~QMediaContainerControl();
virtual QStringList supportedContainers() const = 0;
virtual QString containerMimeType() const = 0;
virtual void setContainerMimeType(const QString &formatMimeType) = 0;
virtual QString containerDescription(const QString &formatMimeType) const = 0;
protected:
QMediaContainerControl(QObject *parent = 0);
};
#define QMediaContainerControl_iid "com.nokia.Qt.QMediaContainerControl/1.0"
Q_MEDIA_DECLARE_CONTROL(QMediaContainerControl, QMediaContainerControl_iid)
QT_END_NAMESPACE
QT_END_HEADER
#endif // QMEDIACONTAINERCONTROL_H

View File

@@ -0,0 +1,254 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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 <QtCore/qurl.h>
#include <QtCore/qvariant.h>
#include "qmediacontent.h"
QT_BEGIN_NAMESPACE
class QMediaContentPrivate : public QSharedData
{
public:
QMediaContentPrivate() {}
QMediaContentPrivate(const QMediaResourceList &r):
resources(r) {}
QMediaContentPrivate(const QMediaContentPrivate &other):
QSharedData(other),
resources(other.resources)
{}
bool operator ==(const QMediaContentPrivate &other) const
{
return resources == other.resources;
}
QMediaResourceList resources;
private:
QMediaContentPrivate& operator=(const QMediaContentPrivate &other);
};
/*!
\class QMediaContent
\brief The QMediaContent class provides access to the resources relating to a media content.
\inmodule QtMultimedia
\ingroup multimedia
\since 1.0
QMediaContent is used within the multimedia framework as the logical handle
to media content. A QMediaContent object is composed of one or more
\l {QMediaResource}s where each resource provides the URL and format
information of a different encoding of the content.
A non-null QMediaContent will always have a primary or canonical reference to
the content available through the canonicalUrl() or canonicalResource()
methods, any additional resources are optional.
*/
/*!
Constructs a null QMediaContent.
*/
QMediaContent::QMediaContent()
{
}
/*!
Constructs a media content with \a url providing a reference to the content.
\since 1.0
*/
QMediaContent::QMediaContent(const QUrl &url):
d(new QMediaContentPrivate)
{
d->resources << QMediaResource(url);
}
/*!
Constructs a media content with \a request providing a reference to the content.
This constructor can be used to reference media content via network protocols such as HTTP.
This may include additional information required to obtain the resource, such as Cookies or HTTP headers.
\since 1.0
*/
QMediaContent::QMediaContent(const QNetworkRequest &request):
d(new QMediaContentPrivate)
{
d->resources << QMediaResource(request);
}
/*!
Constructs a media content with \a resource providing a reference to the content.
\since 1.0
*/
QMediaContent::QMediaContent(const QMediaResource &resource):
d(new QMediaContentPrivate)
{
d->resources << resource;
}
/*!
Constructs a media content with \a resources providing a reference to the content.
\since 1.0
*/
QMediaContent::QMediaContent(const QMediaResourceList &resources):
d(new QMediaContentPrivate(resources))
{
}
/*!
Constructs a copy of the media content \a other.
\since 1.0
*/
QMediaContent::QMediaContent(const QMediaContent &other):
d(other.d)
{
}
/*!
Destroys the media content object.
*/
QMediaContent::~QMediaContent()
{
}
/*!
Assigns the value of \a other to this media content.
\since 1.0
*/
QMediaContent& QMediaContent::operator=(const QMediaContent &other)
{
d = other.d;
return *this;
}
/*!
Returns true if \a other is equivalent to this media content; false otherwise.
\since 1.0
*/
bool QMediaContent::operator==(const QMediaContent &other) const
{
return (d.constData() == 0 && other.d.constData() == 0) ||
(d.constData() != 0 && other.d.constData() != 0 &&
*d.constData() == *other.d.constData());
}
/*!
Returns true if \a other is not equivalent to this media content; false otherwise.
\since 1.0
*/
bool QMediaContent::operator!=(const QMediaContent &other) const
{
return !(*this == other);
}
/*!
Returns true if this media content is null (uninitialized); false otherwise.
\since 1.0
*/
bool QMediaContent::isNull() const
{
return d.constData() == 0;
}
/*!
Returns a QUrl that represents that canonical resource for this media content.
\since 1.0
*/
QUrl QMediaContent::canonicalUrl() const
{
return canonicalResource().url();
}
/*!
Returns a QNetworkRequest that represents that canonical resource for this media content.
\since 1.0
*/
QNetworkRequest QMediaContent::canonicalRequest() const
{
return canonicalResource().request();
}
/*!
Returns a QMediaResource that represents that canonical resource for this media content.
\since 1.0
*/
QMediaResource QMediaContent::canonicalResource() const
{
return d.constData() != 0
? d->resources.value(0)
: QMediaResource();
}
/*!
Returns a list of alternative resources for this media content. The first item in this list
is always the canonical resource.
\since 1.0
*/
QMediaResourceList QMediaContent::resources() const
{
return d.constData() != 0
? d->resources
: QMediaResourceList();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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$
**
****************************************************************************/
#ifndef QMEDIACONTENT_H
#define QMEDIACONTENT_H
#include <QtCore/qmetatype.h>
#include <QtCore/qshareddata.h>
#include "qmediaresource.h"
#include <qtmultimediadefs.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Multimedia)
class QMediaContentPrivate;
class Q_MULTIMEDIA_EXPORT QMediaContent
{
public:
QMediaContent();
QMediaContent(const QUrl &contentUrl);
QMediaContent(const QNetworkRequest &contentRequest);
QMediaContent(const QMediaResource &contentResource);
QMediaContent(const QMediaResourceList &resources);
QMediaContent(const QMediaContent &other);
~QMediaContent();
QMediaContent& operator=(const QMediaContent &other);
bool operator==(const QMediaContent &other) const;
bool operator!=(const QMediaContent &other) const;
bool isNull() const;
QUrl canonicalUrl() const;
QNetworkRequest canonicalRequest() const;
QMediaResource canonicalResource() const;
QMediaResourceList resources() const;
private:
QSharedDataPointer<QMediaContentPrivate> d;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QMediaContent)
QT_END_HEADER
#endif // QMEDIACONTENT_H

Some files were not shown because too many files have changed in this diff Show More