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:
committed by
Qt by Nokia
parent
55bc4f2b46
commit
03f22bcdaf
60
src/multimedia/audio/audio.pri
Normal file
60
src/multimedia/audio/audio.pri
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/multimedia/audio/qaudio.cpp
Normal file
103
src/multimedia/audio/qaudio.cpp
Normal 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
|
||||
|
||||
74
src/multimedia/audio/qaudio.h
Normal file
74
src/multimedia/audio/qaudio.h
Normal 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
|
||||
145
src/multimedia/audio/qaudio_mac.cpp
Normal file
145
src/multimedia/audio/qaudio_mac.cpp
Normal 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
|
||||
|
||||
|
||||
145
src/multimedia/audio/qaudio_mac_p.h
Normal file
145
src/multimedia/audio/qaudio_mac_p.h
Normal 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
|
||||
|
||||
|
||||
288
src/multimedia/audio/qaudiodevicefactory.cpp
Normal file
288
src/multimedia/audio/qaudiodevicefactory.cpp
Normal 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
|
||||
|
||||
100
src/multimedia/audio/qaudiodevicefactory_p.h
Normal file
100
src/multimedia/audio/qaudiodevicefactory_p.h
Normal 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
|
||||
|
||||
483
src/multimedia/audio/qaudiodeviceinfo.cpp
Normal file
483
src/multimedia/audio/qaudiodeviceinfo.cpp
Normal 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
|
||||
|
||||
116
src/multimedia/audio/qaudiodeviceinfo.h
Normal file
116
src/multimedia/audio/qaudiodeviceinfo.h
Normal 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
|
||||
535
src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp
Normal file
535
src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp
Normal 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( ¶ms );
|
||||
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
|
||||
129
src/multimedia/audio/qaudiodeviceinfo_alsa_p.h
Normal file
129
src/multimedia/audio/qaudiodeviceinfo_alsa_p.h
Normal 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
|
||||
|
||||
351
src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp
Normal file
351
src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp
Normal 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
|
||||
|
||||
99
src/multimedia/audio/qaudiodeviceinfo_mac_p.h
Normal file
99
src/multimedia/audio/qaudiodeviceinfo_mac_p.h
Normal 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
|
||||
465
src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp
Normal file
465
src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp
Normal 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
|
||||
120
src/multimedia/audio/qaudiodeviceinfo_win32_p.h
Normal file
120
src/multimedia/audio/qaudiodeviceinfo_win32_p.h
Normal 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
|
||||
407
src/multimedia/audio/qaudioformat.cpp
Normal file
407
src/multimedia/audio/qaudioformat.cpp
Normal 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
|
||||
|
||||
109
src/multimedia/audio/qaudioformat.h
Normal file
109
src/multimedia/audio/qaudioformat.h
Normal 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
|
||||
402
src/multimedia/audio/qaudioinput.cpp
Normal file
402
src/multimedia/audio/qaudioinput.cpp
Normal 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"
|
||||
|
||||
114
src/multimedia/audio/qaudioinput.h
Normal file
114
src/multimedia/audio/qaudioinput.h
Normal 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
|
||||
867
src/multimedia/audio/qaudioinput_alsa_p.cpp
Normal file
867
src/multimedia/audio/qaudioinput_alsa_p.cpp
Normal 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"
|
||||
191
src/multimedia/audio/qaudioinput_alsa_p.h
Normal file
191
src/multimedia/audio/qaudioinput_alsa_p.h
Normal 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
|
||||
989
src/multimedia/audio/qaudioinput_mac_p.cpp
Normal file
989
src/multimedia/audio/qaudioinput_mac_p.cpp
Normal 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"
|
||||
174
src/multimedia/audio/qaudioinput_mac_p.h
Normal file
174
src/multimedia/audio/qaudioinput_mac_p.h
Normal 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
|
||||
642
src/multimedia/audio/qaudioinput_win32_p.cpp
Normal file
642
src/multimedia/audio/qaudioinput_win32_p.cpp
Normal 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"
|
||||
|
||||
179
src/multimedia/audio/qaudioinput_win32_p.h
Normal file
179
src/multimedia/audio/qaudioinput_win32_p.h
Normal 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
|
||||
404
src/multimedia/audio/qaudiooutput.cpp
Normal file
404
src/multimedia/audio/qaudiooutput.cpp
Normal 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"
|
||||
117
src/multimedia/audio/qaudiooutput.h
Normal file
117
src/multimedia/audio/qaudiooutput.h
Normal 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
|
||||
834
src/multimedia/audio/qaudiooutput_alsa_p.cpp
Normal file
834
src/multimedia/audio/qaudiooutput_alsa_p.cpp
Normal 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"
|
||||
175
src/multimedia/audio/qaudiooutput_alsa_p.h
Normal file
175
src/multimedia/audio/qaudiooutput_alsa_p.h
Normal 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
|
||||
734
src/multimedia/audio/qaudiooutput_mac_p.cpp
Normal file
734
src/multimedia/audio/qaudiooutput_mac_p.cpp
Normal 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"
|
||||
174
src/multimedia/audio/qaudiooutput_mac_p.h
Normal file
174
src/multimedia/audio/qaudiooutput_mac_p.h
Normal 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
|
||||
715
src/multimedia/audio/qaudiooutput_win32_p.cpp
Normal file
715
src/multimedia/audio/qaudiooutput_win32_p.cpp
Normal 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"
|
||||
175
src/multimedia/audio/qaudiooutput_win32_p.h
Normal file
175
src/multimedia/audio/qaudiooutput_win32_p.h
Normal 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
|
||||
176
src/multimedia/audio/qaudiopluginloader.cpp
Normal file
176
src/multimedia/audio/qaudiopluginloader.cpp
Normal 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
|
||||
|
||||
100
src/multimedia/audio/qaudiopluginloader_p.h
Normal file
100
src/multimedia/audio/qaudiopluginloader_p.h
Normal 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
|
||||
436
src/multimedia/audio/qaudiosystem.cpp
Normal file
436
src/multimedia/audio/qaudiosystem.cpp
Normal 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"
|
||||
141
src/multimedia/audio/qaudiosystem.h
Normal file
141
src/multimedia/audio/qaudiosystem.h
Normal 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
|
||||
143
src/multimedia/audio/qaudiosystemplugin.cpp
Normal file
143
src/multimedia/audio/qaudiosystemplugin.cpp
Normal 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"
|
||||
96
src/multimedia/audio/qaudiosystemplugin.h
Normal file
96
src/multimedia/audio/qaudiosystemplugin.h
Normal 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
|
||||
36
src/multimedia/effects/effects.pri
Normal file
36
src/multimedia/effects/effects.pri
Normal 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 +=
|
||||
398
src/multimedia/effects/qsamplecache_p.cpp
Normal file
398
src/multimedia/effects/qsamplecache_p.cpp
Normal 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"
|
||||
161
src/multimedia/effects/qsamplecache_p.h
Normal file
161
src/multimedia/effects/qsamplecache_p.h
Normal 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
|
||||
301
src/multimedia/effects/qsoundeffect.cpp
Normal file
301
src/multimedia/effects/qsoundeffect.cpp
Normal 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"
|
||||
143
src/multimedia/effects/qsoundeffect_p.h
Normal file
143
src/multimedia/effects/qsoundeffect_p.h
Normal 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
|
||||
957
src/multimedia/effects/qsoundeffect_pulse_p.cpp
Normal file
957
src/multimedia/effects/qsoundeffect_pulse_p.cpp
Normal 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"
|
||||
163
src/multimedia/effects/qsoundeffect_pulse_p.h
Normal file
163
src/multimedia/effects/qsoundeffect_pulse_p.h
Normal 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
|
||||
233
src/multimedia/effects/qsoundeffect_qmedia_p.cpp
Normal file
233
src/multimedia/effects/qsoundeffect_qmedia_p.cpp
Normal 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"
|
||||
122
src/multimedia/effects/qsoundeffect_qmedia_p.h
Normal file
122
src/multimedia/effects/qsoundeffect_qmedia_p.h
Normal 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
|
||||
222
src/multimedia/effects/qsoundeffect_qsound_p.cpp
Normal file
222
src/multimedia/effects/qsoundeffect_qsound_p.cpp
Normal 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"
|
||||
121
src/multimedia/effects/qsoundeffect_qsound_p.h
Normal file
121
src/multimedia/effects/qsoundeffect_qsound_p.h
Normal 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
|
||||
232
src/multimedia/effects/qwavedecoder_p.cpp
Normal file
232
src/multimedia/effects/qwavedecoder_p.cpp
Normal 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"
|
||||
137
src/multimedia/effects/qwavedecoder_p.h
Normal file
137
src/multimedia/effects/qwavedecoder_p.h
Normal 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
|
||||
156
src/multimedia/multimedia.pro
Normal file
156
src/multimedia/multimedia.pro
Normal 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
|
||||
275
src/multimedia/qaudiocapturesource.cpp
Normal file
275
src/multimedia/qaudiocapturesource.cpp
Normal 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
|
||||
|
||||
103
src/multimedia/qaudiocapturesource.h
Normal file
103
src/multimedia/qaudiocapturesource.h
Normal 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
|
||||
167
src/multimedia/qaudioencodercontrol.cpp
Normal file
167
src/multimedia/qaudioencodercontrol.cpp
Normal 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
|
||||
|
||||
95
src/multimedia/qaudioencodercontrol.h
Normal file
95
src/multimedia/qaudioencodercontrol.h
Normal 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
|
||||
140
src/multimedia/qaudioendpointselector.cpp
Normal file
140
src/multimedia/qaudioendpointselector.cpp
Normal 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
|
||||
|
||||
86
src/multimedia/qaudioendpointselector.h
Normal file
86
src/multimedia/qaudioendpointselector.h
Normal 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
|
||||
70
src/multimedia/qaudionamespace.qdoc
Normal file
70
src/multimedia/qaudionamespace.qdoc
Normal 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
1035
src/multimedia/qcamera.cpp
Normal file
File diff suppressed because it is too large
Load Diff
238
src/multimedia/qcamera.h
Normal file
238
src/multimedia/qcamera.h
Normal 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
|
||||
117
src/multimedia/qcameracapturebufferformatcontrol.cpp
Normal file
117
src/multimedia/qcameracapturebufferformatcontrol.cpp
Normal 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
|
||||
|
||||
81
src/multimedia/qcameracapturebufferformatcontrol.h
Normal file
81
src/multimedia/qcameracapturebufferformatcontrol.h
Normal 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
|
||||
|
||||
121
src/multimedia/qcameracapturedestinationcontrol.cpp
Normal file
121
src/multimedia/qcameracapturedestinationcontrol.cpp
Normal 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
|
||||
|
||||
81
src/multimedia/qcameracapturedestinationcontrol.h
Normal file
81
src/multimedia/qcameracapturedestinationcontrol.h
Normal 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
|
||||
|
||||
215
src/multimedia/qcameracontrol.cpp
Normal file
215
src/multimedia/qcameracontrol.cpp
Normal 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
|
||||
101
src/multimedia/qcameracontrol.h
Normal file
101
src/multimedia/qcameracontrol.h
Normal 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
|
||||
|
||||
646
src/multimedia/qcameraexposure.cpp
Normal file
646
src/multimedia/qcameraexposure.cpp
Normal 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
|
||||
185
src/multimedia/qcameraexposure.h
Normal file
185
src/multimedia/qcameraexposure.h
Normal 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
|
||||
252
src/multimedia/qcameraexposurecontrol.cpp
Normal file
252
src/multimedia/qcameraexposurecontrol.cpp
Normal 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
|
||||
|
||||
124
src/multimedia/qcameraexposurecontrol.h
Normal file
124
src/multimedia/qcameraexposurecontrol.h
Normal 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
|
||||
|
||||
141
src/multimedia/qcameraflashcontrol.cpp
Normal file
141
src/multimedia/qcameraflashcontrol.cpp
Normal 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
|
||||
|
||||
87
src/multimedia/qcameraflashcontrol.h
Normal file
87
src/multimedia/qcameraflashcontrol.h
Normal 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
|
||||
|
||||
478
src/multimedia/qcamerafocus.cpp
Normal file
478
src/multimedia/qcamerafocus.cpp
Normal 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
|
||||
183
src/multimedia/qcamerafocus.h
Normal file
183
src/multimedia/qcamerafocus.h
Normal 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
|
||||
253
src/multimedia/qcamerafocuscontrol.cpp
Normal file
253
src/multimedia/qcamerafocuscontrol.cpp
Normal 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
|
||||
|
||||
103
src/multimedia/qcamerafocuscontrol.h
Normal file
103
src/multimedia/qcamerafocuscontrol.h
Normal 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
|
||||
|
||||
681
src/multimedia/qcameraimagecapture.cpp
Normal file
681
src/multimedia/qcameraimagecapture.cpp
Normal 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
|
||||
|
||||
170
src/multimedia/qcameraimagecapture.h
Normal file
170
src/multimedia/qcameraimagecapture.h
Normal 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
|
||||
|
||||
208
src/multimedia/qcameraimagecapturecontrol.cpp
Normal file
208
src/multimedia/qcameraimagecapturecontrol.cpp
Normal 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
|
||||
|
||||
99
src/multimedia/qcameraimagecapturecontrol.h
Normal file
99
src/multimedia/qcameraimagecapturecontrol.h
Normal 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
|
||||
|
||||
352
src/multimedia/qcameraimageprocessing.cpp
Normal file
352
src/multimedia/qcameraimageprocessing.cpp
Normal 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
|
||||
124
src/multimedia/qcameraimageprocessing.h
Normal file
124
src/multimedia/qcameraimageprocessing.h
Normal 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
|
||||
169
src/multimedia/qcameraimageprocessingcontrol.cpp
Normal file
169
src/multimedia/qcameraimageprocessingcontrol.cpp
Normal 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
|
||||
|
||||
100
src/multimedia/qcameraimageprocessingcontrol.h
Normal file
100
src/multimedia/qcameraimageprocessingcontrol.h
Normal 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
|
||||
|
||||
134
src/multimedia/qcameralockscontrol.cpp
Normal file
134
src/multimedia/qcameralockscontrol.cpp
Normal 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
|
||||
86
src/multimedia/qcameralockscontrol.h
Normal file
86
src/multimedia/qcameralockscontrol.h
Normal 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
|
||||
|
||||
142
src/multimedia/qimageencodercontrol.cpp
Normal file
142
src/multimedia/qimageencodercontrol.cpp
Normal 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
|
||||
|
||||
91
src/multimedia/qimageencodercontrol.h
Normal file
91
src/multimedia/qimageencodercontrol.h
Normal 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
|
||||
194
src/multimedia/qlocalmediaplaylistprovider.cpp
Normal file
194
src/multimedia/qlocalmediaplaylistprovider.cpp
Normal 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
|
||||
|
||||
87
src/multimedia/qlocalmediaplaylistprovider.h
Normal file
87
src/multimedia/qlocalmediaplaylistprovider.h
Normal 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
|
||||
149
src/multimedia/qmediabackgroundplaybackcontrol.cpp
Normal file
149
src/multimedia/qmediabackgroundplaybackcontrol.cpp
Normal 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
|
||||
|
||||
|
||||
83
src/multimedia/qmediabackgroundplaybackcontrol.h
Normal file
83
src/multimedia/qmediabackgroundplaybackcontrol.h
Normal 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
|
||||
85
src/multimedia/qmediabindableinterface.cpp
Normal file
85
src/multimedia/qmediabindableinterface.cpp
Normal 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
|
||||
|
||||
77
src/multimedia/qmediabindableinterface.h
Normal file
77
src/multimedia/qmediabindableinterface.h
Normal 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
|
||||
126
src/multimedia/qmediacontainercontrol.cpp
Normal file
126
src/multimedia/qmediacontainercontrol.cpp
Normal 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
|
||||
|
||||
80
src/multimedia/qmediacontainercontrol.h
Normal file
80
src/multimedia/qmediacontainercontrol.h
Normal 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
|
||||
254
src/multimedia/qmediacontent.cpp
Normal file
254
src/multimedia/qmediacontent.cpp
Normal 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
|
||||
|
||||
95
src/multimedia/qmediacontent.h
Normal file
95
src/multimedia/qmediacontent.h
Normal 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
Reference in New Issue
Block a user