summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin McPherson <justin.mcpherson@nokia.com>2009-08-05 04:26:56 (GMT)
committerJustin McPherson <justin.mcpherson@nokia.com>2009-08-05 04:26:56 (GMT)
commite7052de274f6a201be628441d144dbbef5868948 (patch)
tree2456ce91e33a13d49666213e722a12f32d196e0a
parentbd51c3010e78925a2074122b281de53f01be9ef9 (diff)
downloadQt-e7052de274f6a201be628441d144dbbef5868948.zip
Qt-e7052de274f6a201be628441d144dbbef5868948.tar.gz
Qt-e7052de274f6a201be628441d144dbbef5868948.tar.bz2
Merge AudioServices into mainline.
-rwxr-xr-xbin/syncqt1
-rw-r--r--config.tests/unix/alsa/alsa.pro4
-rw-r--r--config.tests/unix/alsa/alsatest.cpp6
-rwxr-xr-xconfigure36
-rw-r--r--configure.exebin1896493 -> 1134080 bytes
-rw-r--r--demos/qtdemo/xml/examples.xml5
-rw-r--r--doc/src/examples-overview.qdoc11
-rw-r--r--doc/src/examples.qdoc8
-rw-r--r--doc/src/examples/audiodevices.qdoc54
-rw-r--r--doc/src/examples/audioinput.qdoc54
-rw-r--r--doc/src/examples/audiooutput.qdoc52
-rw-r--r--examples/examples.pro1
-rw-r--r--examples/multimedia/README34
-rw-r--r--examples/multimedia/audio/audio.pro10
-rw-r--r--examples/multimedia/audio/audiodevices/audiodevices.cpp272
-rw-r--r--examples/multimedia/audio/audiodevices/audiodevices.h79
-rw-r--r--examples/multimedia/audio/audiodevices/audiodevices.pro12
-rw-r--r--examples/multimedia/audio/audiodevices/audiodevicesbase.ui255
-rw-r--r--examples/multimedia/audio/audiodevices/main.cpp55
-rw-r--r--examples/multimedia/audio/audioinput/audioinput.cpp376
-rw-r--r--examples/multimedia/audio/audioinput/audioinput.h144
-rw-r--r--examples/multimedia/audio/audioinput/audioinput.pro12
-rw-r--r--examples/multimedia/audio/audioinput/main.cpp55
-rw-r--r--examples/multimedia/audio/audiooutput/audiooutput.cpp280
-rw-r--r--examples/multimedia/audio/audiooutput/audiooutput.h112
-rw-r--r--examples/multimedia/audio/audiooutput/audiooutput.pro11
-rw-r--r--examples/multimedia/audio/audiooutput/main.cpp56
-rw-r--r--examples/multimedia/multimedia.pro8
-rw-r--r--mkspecs/features/qt.prf3
-rw-r--r--src/corelib/global/qglobal.h14
-rw-r--r--src/multimedia/audio/audio.pri56
-rw-r--r--src/multimedia/audio/qaudio.cpp102
-rw-r--r--src/multimedia/audio/qaudio.h71
-rw-r--r--src/multimedia/audio/qaudio_mac.cpp142
-rw-r--r--src/multimedia/audio/qaudio_mac_p.h144
-rw-r--r--src/multimedia/audio/qaudiodevicefactory.cpp250
-rw-r--r--src/multimedia/audio/qaudiodevicefactory_p.h100
-rw-r--r--src/multimedia/audio/qaudiodeviceid.cpp168
-rw-r--r--src/multimedia/audio/qaudiodeviceid.h94
-rw-r--r--src/multimedia/audio/qaudiodeviceid_p.h82
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo.cpp270
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo.h102
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp394
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_alsa_p.h113
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp357
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_mac_p.h97
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp378
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_win32_p.h108
-rw-r--r--src/multimedia/audio/qaudioengine.cpp343
-rw-r--r--src/multimedia/audio/qaudioengine.h131
-rw-r--r--src/multimedia/audio/qaudioengineplugin.cpp54
-rw-r--r--src/multimedia/audio/qaudioengineplugin.h93
-rw-r--r--src/multimedia/audio/qaudioformat.cpp335
-rw-r--r--src/multimedia/audio/qaudioformat.h103
-rw-r--r--src/multimedia/audio/qaudioinput.cpp400
-rw-r--r--src/multimedia/audio/qaudioinput.h108
-rw-r--r--src/multimedia/audio/qaudioinput_alsa_p.cpp688
-rw-r--r--src/multimedia/audio/qaudioinput_alsa_p.h151
-rw-r--r--src/multimedia/audio/qaudioinput_mac_p.cpp930
-rw-r--r--src/multimedia/audio/qaudioinput_mac_p.h171
-rw-r--r--src/multimedia/audio/qaudioinput_win32_p.cpp540
-rw-r--r--src/multimedia/audio/qaudioinput_win32_p.h154
-rw-r--r--src/multimedia/audio/qaudiooutput.cpp403
-rw-r--r--src/multimedia/audio/qaudiooutput.h109
-rw-r--r--src/multimedia/audio/qaudiooutput_alsa_p.cpp706
-rw-r--r--src/multimedia/audio/qaudiooutput_alsa_p.h159
-rw-r--r--src/multimedia/audio/qaudiooutput_mac_p.cpp700
-rw-r--r--src/multimedia/audio/qaudiooutput_mac_p.h171
-rw-r--r--src/multimedia/audio/qaudiooutput_win32_p.cpp502
-rw-r--r--src/multimedia/audio/qaudiooutput_win32_p.h154
-rw-r--r--src/multimedia/multimedia.pro11
-rw-r--r--src/plugins/audio/audio.pro3
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/src.pro4
-rw-r--r--tests/auto/auto.pro4
-rw-r--r--tests/auto/qaudiodeviceid/qaudiodeviceid.pro7
-rw-r--r--tests/auto/qaudiodeviceid/tst_qaudiodeviceid.cpp98
-rw-r--r--tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro7
-rw-r--r--tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp159
-rw-r--r--tests/auto/qaudioformat/qaudioformat.pro7
-rw-r--r--tests/auto/qaudioformat/tst_qaudioformat.cpp180
-rw-r--r--tests/auto/qaudioinput/qaudioinput.pro7
-rw-r--r--tests/auto/qaudioinput/tst_qaudioinput.cpp120
-rw-r--r--tests/auto/qaudiooutput/4.wavbin0 -> 5538 bytes
-rw-r--r--tests/auto/qaudiooutput/qaudiooutput.pro12
-rw-r--r--tests/auto/qaudiooutput/tst_qaudiooutput.cpp156
-rw-r--r--tests/auto/tests.xml8
-rw-r--r--tools/configure/configureapp.cpp15
88 files changed, 12950 insertions, 2 deletions
diff --git a/bin/syncqt b/bin/syncqt
index 6c4de6a..589659f 100755
--- a/bin/syncqt
+++ b/bin/syncqt
@@ -43,6 +43,7 @@ my %modules = ( # path to module name map
"QtDBus" => "$basedir/src/dbus",
"QtWebKit" => "$basedir/src/3rdparty/webkit/WebCore",
"phonon" => "$basedir/src/phonon",
+ "QtMultimedia" => "$basedir/src/multimedia",
);
my %moduleheaders = ( # restrict the module headers to those found in relative path
"QtWebKit" => "../WebKit/qt/Api",
diff --git a/config.tests/unix/alsa/alsa.pro b/config.tests/unix/alsa/alsa.pro
new file mode 100644
index 0000000..4931d38
--- /dev/null
+++ b/config.tests/unix/alsa/alsa.pro
@@ -0,0 +1,4 @@
+SOURCES = alsatest.cpp
+LIBS+=-lasound
+CONFIG -= qt dylib
+mac:CONFIG -= app_bundle
diff --git a/config.tests/unix/alsa/alsatest.cpp b/config.tests/unix/alsa/alsatest.cpp
new file mode 100644
index 0000000..af2f5d9
--- /dev/null
+++ b/config.tests/unix/alsa/alsatest.cpp
@@ -0,0 +1,6 @@
+#include <alsa/asoundlib.h>
+int main(int argc,char **argv)
+{
+ return 0;
+}
+
diff --git a/configure b/configure
index 095d040..1d1f826 100755
--- a/configure
+++ b/configure
@@ -609,6 +609,7 @@ CFG_NOBUILD_PARTS=""
CFG_RELEASE_QMAKE=no
CFG_PHONON=auto
CFG_PHONON_BACKEND=yes
+CFG_MULTIMEDIA=yes
CFG_SVG=yes
CFG_WEBKIT=auto # (yes|no|auto)
@@ -709,6 +710,7 @@ OPT_VERBOSE=no
OPT_HELP=
CFG_SILENT=no
CFG_GRAPHICS_SYSTEM=default
+CFG_ALSA=auto
# initalize variables used for installation
QT_INSTALL_PREFIX=
@@ -848,7 +850,7 @@ while [ "$#" -gt 0 ]; do
VAL=no
;;
#Qt style yes options
- -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xshape|-xinput|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-svg|-webkit|-scripttools|-rpath|-force-pkg-config)
+ -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xshape|-xinput|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-svg|-webkit|-scripttools|-rpath|-force-pkg-config)
VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
VAL=yes
;;
@@ -1976,6 +1978,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
+ multimedia)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_MULTIMEDIA="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
*)
UNKNOWN_OPT=yes
;;
@@ -3152,6 +3161,7 @@ Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir
[-no-optimized-qmake] [-optimized-qmake] [-no-xmlpatterns] [-xmlpatterns]
[-no-phonon] [-phonon] [-no-phonon-backend] [-phonon-backend]
[-no-openssl] [-openssl] [-openssl-linked]
+ [-no-multimedia] [-multimedia]
[-no-gtkstyle] [-gtkstyle] [-no-svg] [-svg] [-no-webkit] [-webkit]
[-no-scripttools] [-scripttools]
@@ -3292,6 +3302,9 @@ fi
-no-phonon-backend.. Do not build the platform phonon plugin.
+ -phonon-backend..... Build the platform phonon plugin.
+ -no-multimedia ..... Do not build the multimedia module.
+ * -multimedia ........ Build the multimedia module.
+
-no-svg ............ Do not build the SVG module.
+ -svg ............... Build the SVG module.
@@ -5664,6 +5677,14 @@ if [ "$CFG_PTMALLOC" != "no" ]; then
QMakeVar add QMAKE_LFLAGS "$outpath/lib/libptmalloc3.a"
fi
+if [ "$CFG_ALSA" = "auto" ]; then
+ if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/alsa "alsa" $L_FLAGS $I_FLAGS $l_FLAGS; then
+ CFG_ALSA=yes
+ else
+ CFG_ALSA=no
+ fi
+fi
+
#-------------------------------------------------------------------------------
# ask for all that hasn't been auto-detected or specified in the arguments
#-------------------------------------------------------------------------------
@@ -6104,6 +6125,10 @@ if [ "$CFG_EXCEPTIONS" != "no" ]; then
QTCONFIG_CONFIG="$QTCONFIG_CONFIG exceptions"
fi
+if [ "$CFG_ALSA" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG alsa"
+fi
+
#
# Some Qt modules are too advanced in C++ for some old compilers
# Detect here the platforms where they are known to work.
@@ -6275,6 +6300,12 @@ else
QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SCRIPTTOOLS"
fi
+if [ "$CFG_MULTIMEDIA" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG multimedia"
+else
+ QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_MULTIMEDIA"
+fi
+
if [ "$CFG_EXCEPTIONS" = "no" ]; then
case "$COMPILER" in
g++*)
@@ -6776,6 +6807,7 @@ fi
[ "$CFG_XFIXES" = "runtime" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_RUNTIME_XFIXES"
[ "$CFG_XRANDR" = "runtime" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_RUNTIME_XRANDR"
[ "$CFG_XINPUT" = "runtime" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_RUNTIME_XINPUT"
+[ "$CFG_ALSA" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_ALSA"
# sort QCONFIG_FLAGS for neatness if we can
[ '!' -z "$AWK" ] && QCONFIG_FLAGS=`echo $QCONFIG_FLAGS | $AWK '{ gsub(" ", "\n"); print }' | sort | uniq`
@@ -7135,6 +7167,7 @@ echo "QtConcurrent code.... $CFG_CONCURRENT"
echo "QtScriptTools module $CFG_SCRIPTTOOLS"
echo "QtXmlPatterns module $CFG_XMLPATTERNS"
echo "Phonon module ....... $CFG_PHONON"
+echo "Multimedia module ... $CFG_MULTIMEDIA"
echo "SVG module .......... $CFG_SVG"
echo "WebKit module ....... $CFG_WEBKIT"
echo "STL support ......... $CFG_STL"
@@ -7285,6 +7318,7 @@ if [ "$PLATFORM_MAC" = "yes" ] && [ "$CFG_FRAMEWORK" = "yes" ] && [ "$CFG_DEBUG"
echo "NOTE: Mac OS X frameworks implicitly build debug and release Qt libraries."
echo
fi
+echo "alsa support ........ $CFG_ALSA"
echo
sepath=`echo "$relpath" | sed -e 's/\\./\\\\./g'`
diff --git a/configure.exe b/configure.exe
index 322819e..cf5885a 100644
--- a/configure.exe
+++ b/configure.exe
Binary files differ
diff --git a/demos/qtdemo/xml/examples.xml b/demos/qtdemo/xml/examples.xml
index 006bfd0..1b0b533 100644
--- a/demos/qtdemo/xml/examples.xml
+++ b/demos/qtdemo/xml/examples.xml
@@ -154,6 +154,11 @@
<category dirname="phonon" name="Phonon">
<example filename="musicplayer" name="Music Player" />
</category>
+ <category dirname="multimedia/audio" name="Multimedia">
+ <example filename="audiodevices" name="Audio Devices" />
+ <example filename="audiooutput" name="Audio Output" />
+ <example filename="audioinput" name="Audio Input" />
+ </category>
<category dirname="richtext" name="Rich Text">
<example filename="calendar" name="Calendar" />
<example filename="orderform" name="Order Form" />
diff --git a/doc/src/examples-overview.qdoc b/doc/src/examples-overview.qdoc
index 4313c43..3db4a45 100644
--- a/doc/src/examples-overview.qdoc
+++ b/doc/src/examples-overview.qdoc
@@ -238,6 +238,17 @@
These examples demonstrate the basic techniques used to take advantage of
OpenGL in Qt applications.
+ \section1 \l{Qt Examples#Multimedia}{Multimedia}
+
+ \l{Qt Examples#Multimedia}
+
+ Qt provides low-level audio support on linux,windows and mac platforms by default and
+ an audio plugin API to allow developers to implement there own audio support for
+ custom devices and platforms.
+
+ These examples demonstrate the basic techniques used to take advantage of
+ Audio API in Qt applications.
+
\section1 \l{Qt Examples#SQL}{SQL}
\l{Qt Examples#SQL}{\inlineimage sql-examples.png
diff --git a/doc/src/examples.qdoc b/doc/src/examples.qdoc
index e85acd1..74a9bd8 100644
--- a/doc/src/examples.qdoc
+++ b/doc/src/examples.qdoc
@@ -255,6 +255,14 @@
\o \l{phonon/musicplayer}{Music Player}\raisedaster
\endlist
+ \section1 Multimedia
+
+ \list
+ \o \l{multimedia/audio/audiodevices}{Audio Devices}\raisedaster
+ \o \l{multimedia/audio/audiooutput}{Audio Output}\raisedaster
+ \o \l{multimedia/audio/audioinput}{Audio Input}\raisedaster
+ \endlist
+
\section1 Qt Designer
\list
diff --git a/doc/src/examples/audiodevices.qdoc b/doc/src/examples/audiodevices.qdoc
new file mode 100644
index 0000000..3b8cdd8
--- /dev/null
+++ b/doc/src/examples/audiodevices.qdoc
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example multimedia/audio/audiodevices
+ \title Audio Devices Example
+
+ The Audio Devices example demonstrates the basic use of QAudioDeviceInfo class
+ provided with Qt.
+
+ Qt provides the QAudioDeviceInfo class to enable audio querying within
+ a standard application user interface.
+
+ This example allows you to browse audio devices available and try out different
+ configurations to see if they are supported.
+*/
diff --git a/doc/src/examples/audioinput.qdoc b/doc/src/examples/audioinput.qdoc
new file mode 100644
index 0000000..5dfe76e
--- /dev/null
+++ b/doc/src/examples/audioinput.qdoc
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example multimedia/audio/audioinput
+ \title AudioInput Example
+
+ The Audio Input example demonstrates the basic use of QAudioInput class
+ provided with Qt.
+
+ Qt provides the QAudioInput class to enable audio functionality within
+ a standard application user interface.
+
+ This example uses a fast-fourier transform on the input audio from the microphone
+ and displays the output.
+*/
diff --git a/doc/src/examples/audiooutput.qdoc b/doc/src/examples/audiooutput.qdoc
new file mode 100644
index 0000000..9c8a75f
--- /dev/null
+++ b/doc/src/examples/audiooutput.qdoc
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example multimedia/audio/audiooutput
+ \title Audio Output Example
+
+ The Audio Output example demonstrates the basic use of the QAudioOutput class
+ provided with Qt.
+
+ This example provides a tone generator to supply continuous audio playback.
+ The first button allows pause and resume of the playback.
+ The second button allows toggling between push and pull modes of operation.
+*/
diff --git a/examples/examples.pro b/examples/examples.pro
index 5855e4f..e6cece9 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -26,6 +26,7 @@ SUBDIRS = \
multitouch \
gestures
+contains(QT_CONFIG, multimedia):!static: SUBDIRS += multimedia
contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon
contains(QT_CONFIG, webkit): SUBDIRS += webkit
embedded:SUBDIRS += qws
diff --git a/examples/multimedia/README b/examples/multimedia/README
new file mode 100644
index 0000000..aa78e36
--- /dev/null
+++ b/examples/multimedia/README
@@ -0,0 +1,34 @@
+
+The example launcher provided with Qt can be used to explore each of the
+examples in this directory.
+
+Documentation for these examples can be found via the Tutorial and Examples
+link in the main Qt documentation.
+
+
+Finding the Qt Examples and Demos launcher
+==========================================
+
+On Windows:
+
+The launcher can be accessed via the Windows Start menu. Select the menu
+entry entitled "Qt Examples and Demos" entry in the submenu containing
+the Qt tools.
+
+On Mac OS X:
+
+For the binary distribution, the qtdemo executable is installed in the
+/Developer/Applications/Qt directory. For the source distribution, it is
+installed alongside the other Qt tools on the path specified when Qt is
+configured.
+
+On Unix/Linux:
+
+The qtdemo executable is installed alongside the other Qt tools on the path
+specified when Qt is configured.
+
+On all platforms:
+
+The source code for the launcher can be found in the demos/qtdemo directory
+in the Qt package. This example is built at the same time as the Qt libraries,
+tools, examples, and demonstrations.
diff --git a/examples/multimedia/audio/audio.pro b/examples/multimedia/audio/audio.pro
new file mode 100644
index 0000000..c64bb34
--- /dev/null
+++ b/examples/multimedia/audio/audio.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+SUBDIRS = audioinput \
+ audiooutput \
+ audiodevices
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS audio.pro README
+sources.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio
+INSTALLS += target sources
diff --git a/examples/multimedia/audio/audiodevices/audiodevices.cpp b/examples/multimedia/audio/audiodevices/audiodevices.cpp
new file mode 100644
index 0000000..2a3af98
--- /dev/null
+++ b/examples/multimedia/audio/audiodevices/audiodevices.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QDebug>
+#include <QAudioDeviceInfo>
+
+#include "audiodevices.h"
+
+AudioDevicesBase::AudioDevicesBase( QMainWindow *parent, Qt::WFlags f )
+{
+ Q_UNUSED(parent)
+ Q_UNUSED(f)
+ setupUi( this );
+}
+
+AudioDevicesBase::~AudioDevicesBase() {}
+
+
+AudioTest::AudioTest( QMainWindow *parent, Qt::WFlags f )
+ : AudioDevicesBase( parent, f )
+{
+ mode = QAudio::AudioOutput;
+ modeBox->addItem("Input");
+ modeBox->addItem("Output");
+
+ connect(testButton,SIGNAL(clicked()),SLOT(test()));
+ connect(modeBox,SIGNAL(activated(int)),SLOT(modeChanged(int)));
+ connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
+ connect(frequencyBox,SIGNAL(activated(int)),SLOT(freqChanged(int)));
+ connect(channelsBox,SIGNAL(activated(int)),SLOT(channelChanged(int)));
+ connect(codecsBox,SIGNAL(activated(int)),SLOT(codecChanged(int)));
+ connect(sampleSizesBox,SIGNAL(activated(int)),SLOT(sampleSizeChanged(int)));
+ connect(sampleTypesBox,SIGNAL(activated(int)),SLOT(sampleTypeChanged(int)));
+ connect(endianBox,SIGNAL(activated(int)),SLOT(endianChanged(int)));
+
+ device = 0;
+
+ modeBox->setCurrentIndex(0);
+ modeChanged(0);
+ deviceBox->setCurrentIndex(0);
+ deviceChanged(0);
+}
+
+AudioTest::~AudioTest()
+{
+}
+
+void AudioTest::test()
+{
+ // tries to set all the settings picked.
+
+ if(device) {
+ if(device->isFormatSupported(settings)) {
+ logOutput->append("Success");
+ nearestFreq->setText("");
+ nearestChannel->setText("");
+ nearestCodec->setText("");
+ nearestSampleSize->setText("");
+ nearestSampleType->setText("");
+ nearestEndian->setText("");
+ } else {
+ QAudioFormat nearest = device->nearestFormat(settings);
+ logOutput->append(tr("Failed"));
+ nearestFreq->setText(QString("%1").arg(nearest.frequency()));
+ nearestChannel->setText(QString("%1").arg(nearest.channels()));
+ nearestCodec->setText(nearest.codec());
+ nearestSampleSize->setText(QString("%1").arg(nearest.sampleSize()));
+
+ switch(nearest.sampleType()) {
+ case QAudioFormat::SignedInt:
+ nearestSampleType->setText("SignedInt");
+ break;
+ case QAudioFormat::UnSignedInt:
+ nearestSampleType->setText("UnSignedInt");
+ break;
+ case QAudioFormat::Float:
+ nearestSampleType->setText("Float");
+ break;
+ case QAudioFormat::Unknown:
+ nearestSampleType->setText("Unknown");
+ }
+ switch(nearest.byteOrder()) {
+ case QAudioFormat::LittleEndian:
+ nearestEndian->setText("LittleEndian");
+ break;
+ case QAudioFormat::BigEndian:
+ nearestEndian->setText("BigEndian");
+ }
+ }
+ }
+ else
+ logOutput->append("No Device");
+}
+
+void AudioTest::modeChanged(int idx)
+{
+ // mode has changed
+ if(idx == 0)
+ mode=QAudio::AudioInput;
+ else
+ mode=QAudio::AudioOutput;
+
+ deviceBox->clear();
+ QList<QAudioDeviceId> devices = QAudioDeviceInfo::deviceList(mode);
+ for(int i = 0; i < devices.size(); ++i) {
+ deviceBox->addItem(QAudioDeviceInfo(devices.at(i)).deviceName(), qVariantFromValue(devices.at(i)));
+ }
+}
+
+void AudioTest::deviceChanged(int idx)
+{
+ delete device;
+ device = 0;
+
+ if (deviceBox->count() == 0)
+ return;
+
+ // device has changed
+ deviceHandle = deviceBox->itemData(idx).value<QAudioDeviceId>();
+ device = new QAudioDeviceInfo(deviceHandle, this);
+
+ frequencyBox->clear();
+ QList<int> freqz = device->supportedFrequencies();
+ for(int i = 0; i < freqz.size(); ++i)
+ frequencyBox->addItem(QString("%1").arg(freqz.at(i)));
+ if(freqz.size())
+ settings.setFrequency(freqz.at(0));
+
+ channelsBox->clear();
+ QList<int> chz = device->supportedChannels();
+ for(int i = 0; i < chz.size(); ++i)
+ channelsBox->addItem(QString("%1").arg(chz.at(i)));
+ if(chz.size())
+ settings.setChannels(chz.at(0));
+
+ codecsBox->clear();
+ QStringList codecz = device->supportedCodecs();
+ for(int i = 0; i < codecz.size(); ++i)
+ codecsBox->addItem(QString("%1").arg(codecz.at(i)));
+ if(codecz.size())
+ settings.setCodec(codecz.at(0));
+ // Add false to create failed condition!
+ codecsBox->addItem("audio/mpeg");
+
+ sampleSizesBox->clear();
+ QList<int> sampleSizez = device->supportedSampleSizes();
+ for(int i = 0; i < sampleSizez.size(); ++i)
+ sampleSizesBox->addItem(QString("%1").arg(sampleSizez.at(i)));
+ if(sampleSizez.size())
+ settings.setSampleSize(sampleSizez.at(0));
+
+ sampleTypesBox->clear();
+ QList<QAudioFormat::SampleType> sampleTypez = device->supportedSampleTypes();
+ for(int i = 0; i < sampleTypez.size(); ++i) {
+ switch(sampleTypez.at(i)) {
+ case QAudioFormat::SignedInt:
+ sampleTypesBox->addItem("SignedInt");
+ break;
+ case QAudioFormat::UnSignedInt:
+ sampleTypesBox->addItem("UnSignedInt");
+ break;
+ case QAudioFormat::Float:
+ sampleTypesBox->addItem("Float");
+ break;
+ case QAudioFormat::Unknown:
+ sampleTypesBox->addItem("Unknown");
+ }
+ if(sampleTypez.size())
+ settings.setSampleType(sampleTypez.at(0));
+ }
+
+ endianBox->clear();
+ QList<QAudioFormat::Endian> endianz = device->supportedByteOrders();
+ for(int i = 0; i < endianz.size(); ++i) {
+ switch(endianz.at(i)) {
+ case QAudioFormat::LittleEndian:
+ endianBox->addItem("Little Endian");
+ break;
+ case QAudioFormat::BigEndian:
+ endianBox->addItem("Big Endian");
+ break;
+ }
+ }
+ if(endianz.size())
+ settings.setByteOrder(endianz.at(0));
+}
+
+void AudioTest::freqChanged(int idx)
+{
+ // freq has changed
+ settings.setFrequency(frequencyBox->itemText(idx).toInt());
+}
+
+void AudioTest::channelChanged(int idx)
+{
+ settings.setChannels(channelsBox->itemText(idx).toInt());
+}
+
+void AudioTest::codecChanged(int idx)
+{
+ settings.setCodec(codecsBox->itemText(idx));
+}
+
+void AudioTest::sampleSizeChanged(int idx)
+{
+ settings.setSampleSize(sampleSizesBox->itemText(idx).toInt());
+}
+
+void AudioTest::sampleTypeChanged(int idx)
+{
+ switch(sampleTypesBox->itemText(idx).toInt()) {
+ case QAudioFormat::SignedInt:
+ settings.setSampleType(QAudioFormat::SignedInt);
+ break;
+ case QAudioFormat::UnSignedInt:
+ settings.setSampleType(QAudioFormat::UnSignedInt);
+ break;
+ case QAudioFormat::Float:
+ settings.setSampleType(QAudioFormat::Float);
+ }
+}
+
+void AudioTest::endianChanged(int idx)
+{
+ switch(endianBox->itemText(idx).toInt()) {
+ case QAudioFormat::LittleEndian:
+ settings.setByteOrder(QAudioFormat::LittleEndian);
+ break;
+ case QAudioFormat::BigEndian:
+ settings.setByteOrder(QAudioFormat::BigEndian);
+ }
+}
+
diff --git a/examples/multimedia/audio/audiodevices/audiodevices.h b/examples/multimedia/audio/audiodevices/audiodevices.h
new file mode 100644
index 0000000..34a531b
--- /dev/null
+++ b/examples/multimedia/audio/audiodevices/audiodevices.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QObject>
+#include <QMainWindow>
+#include <QAudioDeviceInfo>
+
+#include "ui_audiodevicesbase.h"
+
+class AudioDevicesBase : public QMainWindow, public Ui::AudioDevicesBase
+{
+public:
+ AudioDevicesBase( QMainWindow *parent = 0, Qt::WFlags f = 0 );
+ virtual ~AudioDevicesBase();
+};
+
+class AudioTest : public AudioDevicesBase
+{
+ Q_OBJECT
+public:
+ AudioTest( QMainWindow *parent = 0, Qt::WFlags f = 0 );
+ virtual ~AudioTest();
+
+ QAudioDeviceId deviceHandle;
+ QAudioDeviceInfo* device;
+ QAudioFormat settings;
+ QAudio::Mode mode;
+
+private slots:
+ void modeChanged(int idx);
+ void deviceChanged(int idx);
+ void freqChanged(int idx);
+ void channelChanged(int idx);
+ void codecChanged(int idx);
+ void sampleSizeChanged(int idx);
+ void sampleTypeChanged(int idx);
+ void endianChanged(int idx);
+ void test();
+};
+
diff --git a/examples/multimedia/audio/audiodevices/audiodevices.pro b/examples/multimedia/audio/audiodevices/audiodevices.pro
new file mode 100644
index 0000000..adc4890
--- /dev/null
+++ b/examples/multimedia/audio/audiodevices/audiodevices.pro
@@ -0,0 +1,12 @@
+HEADERS = audiodevices.h
+SOURCES = audiodevices.cpp \
+ main.cpp
+FORMS += audiodevicesbase.ui
+
+QT += multimedia
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio/audiodevices
+sources.files = $$SOURCES *.h $$RESOURCES $$FORMS audiodevices.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio/audiodevices
+INSTALLS += target sources
diff --git a/examples/multimedia/audio/audiodevices/audiodevicesbase.ui b/examples/multimedia/audio/audiodevices/audiodevicesbase.ui
new file mode 100644
index 0000000..674f201
--- /dev/null
+++ b/examples/multimedia/audio/audiodevices/audiodevicesbase.ui
@@ -0,0 +1,255 @@
+<ui version="4.0" >
+ <class>AudioDevicesBase</class>
+ <widget class="QMainWindow" name="AudioDevicesBase" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>504</width>
+ <height>702</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>AudioDevicesBase</string>
+ </property>
+ <widget class="QWidget" name="centralwidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>504</width>
+ <height>653</height>
+ </rect>
+ </property>
+ <widget class="QWidget" name="layoutWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>40</x>
+ <y>21</y>
+ <width>321</width>
+ <height>506</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="deviceLabel" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Device</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLabel" name="modeLabel" >
+ <property name="text" >
+ <string>Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QComboBox" name="deviceBox" />
+ </item>
+ <item row="1" column="1" >
+ <widget class="QComboBox" name="modeBox" />
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="actualLabel" >
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text" >
+ <string>Actual Settings</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QLabel" name="nearestLabel" >
+ <property name="frameShape" >
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text" >
+ <string>Nearest Settings</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="actualFreqLabel" >
+ <property name="text" >
+ <string>Frequency</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QLabel" name="nearestFreqLabel" >
+ <property name="text" >
+ <string>Frequency</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" >
+ <widget class="QComboBox" name="frequencyBox" />
+ </item>
+ <item row="4" column="1" >
+ <widget class="QLineEdit" name="nearestFreq" />
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="actualChannelsLabel" >
+ <property name="text" >
+ <string>Channels</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" >
+ <widget class="QLabel" name="nearestChannelLabel" >
+ <property name="text" >
+ <string>Channel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" >
+ <widget class="QComboBox" name="channelsBox" />
+ </item>
+ <item row="6" column="1" >
+ <widget class="QLineEdit" name="nearestChannel" />
+ </item>
+ <item row="7" column="0" >
+ <widget class="QLabel" name="actualCodecLabel" >
+ <property name="text" >
+ <string>Codecs</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1" >
+ <widget class="QLabel" name="nearestCodecLabel" >
+ <property name="text" >
+ <string>Codec</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0" >
+ <widget class="QComboBox" name="codecsBox" />
+ </item>
+ <item row="8" column="1" >
+ <widget class="QLineEdit" name="nearestCodec" />
+ </item>
+ <item row="9" column="0" >
+ <widget class="QLabel" name="actualSampleSizeLabel" >
+ <property name="text" >
+ <string>SampleSize</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1" >
+ <widget class="QLabel" name="nearestSampleSizeLabel" >
+ <property name="text" >
+ <string>SampleSize</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0" >
+ <widget class="QComboBox" name="sampleSizesBox" />
+ </item>
+ <item row="10" column="1" >
+ <widget class="QLineEdit" name="nearestSampleSize" />
+ </item>
+ <item row="11" column="0" >
+ <widget class="QLabel" name="actualSampleTypeLabel" >
+ <property name="text" >
+ <string>SampleType</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1" >
+ <widget class="QLabel" name="nearestSampleTypeLabel" >
+ <property name="text" >
+ <string>SampleType</string>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="0" >
+ <widget class="QComboBox" name="sampleTypesBox" />
+ </item>
+ <item row="12" column="1" >
+ <widget class="QLineEdit" name="nearestSampleType" />
+ </item>
+ <item row="13" column="0" >
+ <widget class="QLabel" name="actualEndianLabel" >
+ <property name="text" >
+ <string>Endianess</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="1" >
+ <widget class="QLabel" name="nearestEndianLabel" >
+ <property name="text" >
+ <string>Endianess</string>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="0" >
+ <widget class="QComboBox" name="endianBox" />
+ </item>
+ <item row="14" column="1" >
+ <widget class="QLineEdit" name="nearestEndian" />
+ </item>
+ <item row="15" column="0" colspan="2" >
+ <widget class="QTextEdit" name="logOutput" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>40</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="0" colspan="2" >
+ <widget class="QPushButton" name="testButton" >
+ <property name="text" >
+ <string>Test</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>504</width>
+ <height>28</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>681</y>
+ <width>504</width>
+ <height>21</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/multimedia/audio/audiodevices/main.cpp b/examples/multimedia/audio/audiodevices/main.cpp
new file mode 100644
index 0000000..12e413e
--- /dev/null
+++ b/examples/multimedia/audio/audiodevices/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "audiodevices.h"
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Audio Device Test");
+
+ AudioTest audio;
+ audio.show();
+
+ return app.exec();
+}
diff --git a/examples/multimedia/audio/audioinput/audioinput.cpp b/examples/multimedia/audio/audioinput/audioinput.cpp
new file mode 100644
index 0000000..ae7d84c
--- /dev/null
+++ b/examples/multimedia/audio/audioinput/audioinput.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdlib.h>
+#include <math.h>
+
+#include <QDebug>
+#include <QPainter>
+#include <QVBoxLayout>
+
+#include <QAudioDeviceInfo>
+#include <QAudioInput>
+#include "audioinput.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+Spectrum::Spectrum(QObject* parent, QAudioInput* device, float* out)
+ :QIODevice( parent )
+{
+ input = device;
+ output = out;
+
+ unsigned int i;
+
+ // Allocate sample buffer and initialize sin and cos lookup tables
+ fftState = (fft_state *) malloc (sizeof(fft_state));
+
+ for(i = 0; i < BUFFER_SIZE; i++) {
+ bitReverse[i] = reverseBits(i);
+ }
+ for(i = 0; i < BUFFER_SIZE / 2; i++) {
+ float j = 2 * M_PI * i / BUFFER_SIZE;
+ costable[i] = cos(j);
+ sintable[i] = sin(j);
+ }
+}
+
+Spectrum::~Spectrum()
+{
+}
+
+void Spectrum::start()
+{
+ open(QIODevice::WriteOnly);
+}
+
+void Spectrum::stop()
+{
+ close();
+}
+
+qint64 Spectrum::readData(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data)
+ Q_UNUSED(maxlen)
+
+ return 0;
+}
+
+qint64 Spectrum::writeData(const char *data, qint64 len)
+{
+ performFFT((sound_sample*)data);
+ emit update();
+
+ return len;
+}
+
+int Spectrum::reverseBits(unsigned int initial) {
+ // BIT-REVERSE-COPY(a,A)
+
+ unsigned int reversed = 0, loop;
+ for(loop = 0; loop < BUFFER_SIZE_LOG; loop++) {
+ reversed <<= 1;
+ reversed += (initial & 1);
+ initial >>= 1;
+ }
+ return reversed;
+}
+
+void Spectrum::performFFT(const sound_sample *input) {
+ /* Convert to reverse bit order for FFT */
+ prepFFT(input, fftState->real, fftState->imag);
+
+ /* Calculate FFT */
+ calcFFT(fftState->real, fftState->imag);
+
+ /* Convert FFT to intensities */
+ outputFFT(fftState->real, fftState->imag);
+}
+
+void Spectrum::prepFFT(const sound_sample *input, float * re, float * im) {
+ unsigned int i;
+ float *realptr = re;
+ float *imagptr = im;
+
+ /* Get input, in reverse bit order */
+ for(i = 0; i < BUFFER_SIZE; i++) {
+ *realptr++ = input[bitReverse[i]];
+ *imagptr++ = 0;
+ }
+}
+
+void Spectrum::calcFFT(float * re, float * im) {
+ unsigned int i, j, k;
+ unsigned int exchanges;
+ float fact_real, fact_imag;
+ float tmp_real, tmp_imag;
+ unsigned int factfact;
+
+ /* Set up some variables to reduce calculation in the loops */
+ exchanges = 1;
+ factfact = BUFFER_SIZE / 2;
+
+ /* divide and conquer method */
+ for(i = BUFFER_SIZE_LOG; i != 0; i--) {
+ for(j = 0; j != exchanges; j++) {
+ fact_real = costable[j * factfact];
+ fact_imag = sintable[j * factfact];
+ for(k = j; k < BUFFER_SIZE; k += exchanges << 1) {
+ int k1 = k + exchanges;
+ tmp_real = fact_real * re[k1] - fact_imag * im[k1];
+ tmp_imag = fact_real * im[k1] + fact_imag * re[k1];
+ re[k1] = re[k] - tmp_real;
+ im[k1] = im[k] - tmp_imag;
+ re[k] += tmp_real;
+ im[k] += tmp_imag;
+ }
+ }
+ exchanges <<= 1;
+ factfact >>= 1;
+ }
+}
+
+void Spectrum::outputFFT(const float * re, const float * im) {
+ const float *realptr = re;
+ const float *imagptr = im;
+ float *outputptr = output;
+
+ float *endptr = output + BUFFER_SIZE / 2;
+
+ /* Convert FFT to intensities */
+
+ while(outputptr <= endptr) {
+ *outputptr = (*realptr * *realptr) + (*imagptr * *imagptr);
+ outputptr++; realptr++; imagptr++;
+ }
+ *output /= 4;
+ *endptr /= 4;
+}
+
+
+RenderArea::RenderArea(QWidget *parent)
+ : QWidget(parent)
+{
+ setBackgroundRole(QPalette::Base);
+ setAutoFillBackground(true);
+
+ samples = 0;
+ sampleSize = 0;
+ setMinimumHeight(30);
+ setMinimumWidth(200);
+}
+
+void RenderArea::paintEvent(QPaintEvent * /* event */)
+{
+ QPainter painter(this);
+
+ if(sampleSize == 0)
+ return;
+
+ painter.setPen(Qt::red);
+ int max = 0;
+ for(int i=0;i<sampleSize;i++) {
+ int m = (int)(sqrt(samples[i])/32768);
+ if(m > max)
+ max = m;
+ }
+ int x1,y1,x2,y2;
+
+ for(int i=0;i<10;i++) {
+ x1 = painter.viewport().left()+11;
+ y1 = painter.viewport().top()+10+i;
+ x2 = painter.viewport().right()-20-max;
+ y2 = painter.viewport().top()+10+i;
+ if(x2 < painter.viewport().left()+10)
+ x2 = painter.viewport().left()+10;
+
+ painter.drawLine(QPoint(x1,y1),QPoint(x2,y2));
+ }
+
+ painter.setPen(Qt::black);
+ painter.drawRect(QRect(painter.viewport().left()+10, painter.viewport().top()+10,
+ painter.viewport().right()-20, painter.viewport().bottom()-20));
+}
+
+void RenderArea::spectrum(float* output, int size)
+{
+ samples = output;
+ sampleSize = size;
+ repaint();
+}
+
+
+InputTest::InputTest()
+{
+ QWidget *window = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout;
+
+ canvas = new RenderArea;
+ layout->addWidget(canvas);
+
+ deviceBox = new QComboBox(this);
+ QList<QAudioDeviceId> devices = QAudioDeviceInfo::deviceList(QAudio::AudioInput);
+ for(int i = 0; i < devices.size(); ++i) {
+ deviceBox->addItem(QAudioDeviceInfo(devices.at(i)).deviceName(), qVariantFromValue(devices.at(i)));
+ }
+ connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
+ layout->addWidget(deviceBox);
+
+ button = new QPushButton(this);
+ button->setText(tr("Click for Push Mode"));
+ connect(button,SIGNAL(clicked()),SLOT(toggleMode()));
+ layout->addWidget(button);
+
+ button2 = new QPushButton(this);
+ button2->setText(tr("Click To Suspend"));
+ connect(button2,SIGNAL(clicked()),SLOT(toggleSuspend()));
+ layout->addWidget(button2);
+
+ window->setLayout(layout);
+ setCentralWidget(window);
+ window->show();
+
+ buffer = new char[BUFFER_SIZE*10];
+ output = new float[1024];
+
+ pullMode = true;
+
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setCodec("audio/pcm");
+
+ audioInput = new QAudioInput(format,this);
+ connect(audioInput,SIGNAL(notify()),SLOT(status()));
+ connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
+ spec = new Spectrum(this,audioInput,output);
+ connect(spec,SIGNAL(update()),SLOT(refreshDisplay()));
+ spec->start();
+ audioInput->start(spec);
+}
+
+InputTest::~InputTest() {}
+
+void InputTest::status()
+{
+ qWarning()<<"bytesReady = "<<audioInput->bytesReady()<<" bytes, clock = "<<audioInput->clock()<<"ms, totalTime = "<<audioInput->totalTime()/1000<<"ms";
+}
+
+void InputTest::readMore()
+{
+ if(!audioInput)
+ return;
+ qint64 len = audioInput->bytesReady();
+ if(len > BUFFER_SIZE*10)
+ len = BUFFER_SIZE*10;
+ qint64 l = input->read(buffer,len);
+ if(l > 0) {
+ spec->write(buffer,l);
+ }
+}
+
+void InputTest::toggleMode()
+{
+ // Change bewteen pull and push modes
+ audioInput->stop();
+
+ if(pullMode) {
+ button->setText(tr("Click for Push Mode"));
+ input = audioInput->start(0);
+ connect(input,SIGNAL(readyRead()),SLOT(readMore()));
+ pullMode = false;
+ } else {
+ button->setText(tr("Click for Pull Mode"));
+ pullMode = true;
+ audioInput->start(spec);
+ }
+}
+
+void InputTest::toggleSuspend()
+{
+ // toggle suspend/resume
+ if(audioInput->state() == QAudio::SuspendState) {
+ qWarning()<<"status: Suspended, resume()";
+ audioInput->resume();
+ button2->setText("Click To Suspend");
+ } else if (audioInput->state() == QAudio::ActiveState) {
+ qWarning()<<"status: Active, suspend()";
+ audioInput->suspend();
+ button2->setText("Click To Resume");
+ } else if (audioInput->state() == QAudio::StopState) {
+ qWarning()<<"status: Stopped, resume()";
+ audioInput->resume();
+ button2->setText("Click To Suspend");
+ } else if (audioInput->state() == QAudio::IdleState) {
+ qWarning()<<"status: IdleState";
+ }
+}
+
+void InputTest::state(QAudio::State state)
+{
+ qWarning()<<" state="<<state;
+}
+
+void InputTest::refreshDisplay()
+{
+ canvas->spectrum(output,256);
+ canvas->repaint();
+}
+
+void InputTest::deviceChanged(int idx)
+{
+ spec->stop();
+ audioInput->stop();
+ audioInput->disconnect(this);
+ delete audioInput;
+
+ device = deviceBox->itemData(idx).value<QAudioDeviceId>();
+ audioInput = new QAudioInput(device, format, this);
+ connect(audioInput,SIGNAL(notify()),SLOT(status()));
+ connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
+ spec->start();
+ audioInput->start(spec);
+}
diff --git a/examples/multimedia/audio/audioinput/audioinput.h b/examples/multimedia/audio/audioinput/audioinput.h
new file mode 100644
index 0000000..3a6b356
--- /dev/null
+++ b/examples/multimedia/audio/audioinput/audioinput.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QPixmap>
+#include <QWidget>
+#include <QObject>
+#include <QMainWindow>
+#include <QPushButton>
+#include <QComboBox>
+
+#include <qaudioinput.h>
+
+#define BUFFER_SIZE_LOG 9
+#define BUFFER_SIZE (1 << BUFFER_SIZE_LOG)
+
+struct _struct_fft_state {
+ float real[BUFFER_SIZE];
+ float imag[BUFFER_SIZE];
+};
+typedef _struct_fft_state fft_state;
+typedef short int sound_sample;
+
+class Spectrum : public QIODevice
+{
+ Q_OBJECT
+public:
+ Spectrum(QObject* parent, QAudioInput* device, float* out);
+ ~Spectrum();
+
+ void start();
+ void stop();
+
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+
+ QAudioInput* input;
+ float* output;
+ fft_state* fftState;
+
+ unsigned int bitReverse[BUFFER_SIZE];
+ float sintable[BUFFER_SIZE / 2];
+ float costable[BUFFER_SIZE / 2];
+
+ void prepFFT (const sound_sample *input, float *re, float *im);
+ void calcFFT (float *re, float *im);
+ void outputFFT (const float *re, const float *im);
+ int reverseBits (unsigned int initial);
+ void performFFT (const sound_sample *input);
+
+signals:
+ void update();
+};
+
+
+class RenderArea : public QWidget
+{
+ Q_OBJECT
+
+public:
+ RenderArea(QWidget *parent = 0);
+
+ void spectrum(float* output, int size);
+
+protected:
+ void paintEvent(QPaintEvent *event);
+
+private:
+ QPixmap pixmap;
+
+ float* samples;
+ int sampleSize;
+};
+
+class InputTest : public QMainWindow
+{
+ Q_OBJECT
+public:
+ InputTest();
+ ~InputTest();
+
+ QAudioDeviceId device;
+ QAudioFormat format;
+ QAudioInput* audioInput;
+ Spectrum* spec;
+ QIODevice* input;
+ RenderArea* canvas;
+
+ bool pullMode;
+
+ QPushButton* button;
+ QPushButton* button2;
+ QComboBox* deviceBox;
+
+ char* buffer;
+ float* output;
+
+private slots:
+ void refreshDisplay();
+ void status();
+ void readMore();
+ void toggleMode();
+ void toggleSuspend();
+ void state(QAudio::State s);
+ void deviceChanged(int idx);
+};
+
diff --git a/examples/multimedia/audio/audioinput/audioinput.pro b/examples/multimedia/audio/audioinput/audioinput.pro
new file mode 100644
index 0000000..d930750
--- /dev/null
+++ b/examples/multimedia/audio/audioinput/audioinput.pro
@@ -0,0 +1,12 @@
+HEADERS = audioinput.h
+SOURCES = audioinput.cpp \
+ main.cpp
+
+QT += multimedia
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio/audioinput
+sources.files = $$SOURCES *.h $$RESOURCES $$FORMS audioinput.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio/audioinput
+INSTALLS += target sources
+
diff --git a/examples/multimedia/audio/audioinput/main.cpp b/examples/multimedia/audio/audioinput/main.cpp
new file mode 100644
index 0000000..64a9b04
--- /dev/null
+++ b/examples/multimedia/audio/audioinput/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "audioinput.h"
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Audio Input Test");
+
+ InputTest input;
+ input.show();
+
+ return app.exec();
+}
diff --git a/examples/multimedia/audio/audiooutput/audiooutput.cpp b/examples/multimedia/audio/audiooutput/audiooutput.cpp
new file mode 100644
index 0000000..be26f19
--- /dev/null
+++ b/examples/multimedia/audio/audiooutput/audiooutput.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QVBoxLayout>
+
+#include <QAudioOutput>
+#include <QAudioDeviceInfo>
+#include "audiooutput.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+Generator::Generator(QObject *parent)
+ :QIODevice( parent )
+{
+ finished = false;
+ buffer = new char[SECONDS*44100*4+1000];
+ t=buffer;
+ len=fillData(t+4,450,SECONDS); /* left channel, 450Hz sine */
+ len+=fillData(t+6,452,SECONDS); /* right channel, 452Hz sine */
+ putLong(t,len);
+ putLong(buffer+4,len+8+16+8);
+ pos = 0;
+ total = len+8+16+8;
+}
+
+Generator::~Generator()
+{
+ delete [] buffer;
+}
+
+void Generator::start()
+{
+ open(QIODevice::ReadOnly);
+}
+
+void Generator::stop()
+{
+ close();
+}
+
+int Generator::putShort(char *t, unsigned int value)
+{
+ *(unsigned char *)(t++)=value&255;
+ *(unsigned char *)(t)=(value/256)&255;
+ return 2;
+}
+
+int Generator::putLong(char *t, unsigned int value)
+{
+ *(unsigned char *)(t++)=value&255;
+ *(unsigned char *)(t++)=(value/256)&255;
+ *(unsigned char *)(t++)=(value/(256*256))&255;
+ *(unsigned char *)(t)=(value/(256*256*256))&255;
+ return 4;
+}
+
+int Generator::fillData(char *start, int frequency, int seconds)
+{
+ int i, len=0;
+ int value;
+ for(i=0; i<seconds*44100; i++) {
+ value=(int)(32767.0*sin(2.0*M_PI*((double)(i))*(double)(frequency)/44100.0));
+ putShort(start, value);
+ start += 4;
+ len+=2;
+ }
+ return len;
+}
+
+qint64 Generator::readData(char *data, qint64 maxlen)
+{
+ int len = maxlen;
+ if(len > 16384)
+ len = 16384;
+
+ if(len < (SECONDS*44100*4+1000)-pos) {
+ // Normal
+ memcpy(data,t+pos,len);
+ pos+=len;
+ return len;
+ } else {
+ // Whats left and reset to start
+ qint64 left = (SECONDS*44100*4+1000)-pos;
+ memcpy(data,t+pos,left);
+ pos=0;
+ return left;
+ }
+}
+
+qint64 Generator::writeData(const char *data, qint64 len)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(len);
+
+ return 0;
+}
+
+AudioTest::AudioTest()
+{
+ QWidget *window = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout;
+
+ deviceBox = new QComboBox(this);
+ QList<QAudioDeviceId> devices = QAudioDeviceInfo::deviceList(QAudio::AudioOutput);
+ for(int i = 0; i < devices.size(); ++i) {
+ deviceBox->addItem(QAudioDeviceInfo(devices.at(i)).deviceName(), qVariantFromValue(devices.at(i)));
+ }
+ connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
+ layout->addWidget(deviceBox);
+
+ button = new QPushButton(this);
+ button->setText(tr("Click for Push Mode"));
+ connect(button,SIGNAL(clicked()),SLOT(toggle()));
+ layout->addWidget(button);
+
+ button2 = new QPushButton(this);
+ button2->setText(tr("Click To Suspend"));
+ connect(button2,SIGNAL(clicked()),SLOT(togglePlay()));
+ layout->addWidget(button2);
+
+ window->setLayout(layout);
+ setCentralWidget(window);
+ window->show();
+
+ buffer = new char[BUFFER_SIZE];
+
+ gen = new Generator(this);
+
+ pullMode = true;
+
+ timer = new QTimer(this);
+ connect(timer,SIGNAL(timeout()),SLOT(writeMore()));
+
+ gen->start();
+
+ settings.setFrequency(44100);
+ settings.setChannels(2);
+ settings.setSampleSize(16);
+ settings.setCodec("audio/pcm");
+ settings.setByteOrder(QAudioFormat::LittleEndian);
+ settings.setSampleType(QAudioFormat::SignedInt);
+ audioOutput = new QAudioOutput(settings,this);
+ connect(audioOutput,SIGNAL(notify()),SLOT(status()));
+ connect(audioOutput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
+
+ audioOutput->start(gen);
+}
+
+AudioTest::~AudioTest()
+{
+ delete [] buffer;
+}
+
+void AudioTest::deviceChanged(int idx)
+{
+ timer->stop();
+ gen->stop();
+ audioOutput->stop();
+ audioOutput->disconnect(this);
+ delete audioOutput;
+
+ device = deviceBox->itemData(idx).value<QAudioDeviceId>();
+ audioOutput = new QAudioOutput(device,settings,this);
+ connect(audioOutput,SIGNAL(notify()),SLOT(status()));
+ connect(audioOutput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
+ gen->start();
+ audioOutput->start(gen);
+}
+
+void AudioTest::status()
+{
+ qWarning()<<"byteFree = "<<audioOutput->bytesFree()<<" bytes, clock = "<<audioOutput->clock()<<"ms, totalTime = "<<audioOutput->totalTime()/1000<<"ms";
+}
+
+void AudioTest::writeMore()
+{
+ if(!audioOutput)
+ return;
+
+ if(audioOutput->state() == QAudio::StopState)
+ return;
+
+ int l;
+ int out;
+
+ int chunks = audioOutput->bytesFree()/audioOutput->periodSize();
+ while(chunks) {
+ l = gen->read(buffer,audioOutput->periodSize());
+ if(l > 0)
+ out = output->write(buffer,l);
+ if(l != audioOutput->periodSize())
+ break;
+ chunks--;
+ }
+}
+
+void AudioTest::toggle()
+{
+ // Change between pull and push modes
+
+ timer->stop();
+ audioOutput->stop();
+
+ if (pullMode) {
+ button->setText("Click for Pull Mode");
+ output = audioOutput->start(0);
+ pullMode = false;
+ timer->start(20);
+ } else {
+ button->setText("Click for Push Mode");
+ pullMode = true;
+ audioOutput->start(gen);
+ }
+}
+
+void AudioTest::togglePlay()
+{
+ // toggle suspend/resume
+ if(audioOutput->state() == QAudio::SuspendState) {
+ qWarning()<<"status: Suspended, resume()";
+ audioOutput->resume();
+ button2->setText("Click To Suspend");
+ } else if (audioOutput->state() == QAudio::ActiveState) {
+ qWarning()<<"status: Active, suspend()";
+ audioOutput->suspend();
+ button2->setText("Click To Resume");
+ } else if (audioOutput->state() == QAudio::StopState) {
+ qWarning()<<"status: Stopped, resume()";
+ audioOutput->resume();
+ button2->setText("Click To Suspend");
+ } else if (audioOutput->state() == QAudio::IdleState) {
+ qWarning()<<"status: IdleState";
+ }
+}
+
+void AudioTest::state(QAudio::State state)
+{
+ qWarning()<<" state="<<state;
+}
diff --git a/examples/multimedia/audio/audiooutput/audiooutput.h b/examples/multimedia/audio/audiooutput/audiooutput.h
new file mode 100644
index 0000000..1e21b48
--- /dev/null
+++ b/examples/multimedia/audio/audiooutput/audiooutput.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <math.h>
+
+#define BUFFER_SIZE 32768
+#define SECONDS 3
+
+#include <QObject>
+#include <QMainWindow>
+#include <QIODevice>
+#include <QTimer>
+#include <QPushButton>
+#include <QComboBox>
+
+#include <QAudioOutput>
+
+class Generator : public QIODevice
+{
+ Q_OBJECT
+public:
+ Generator(QObject *parent);
+ ~Generator();
+
+ void start();
+ void stop();
+
+ char *t;
+ int len;
+ int pos;
+ int total;
+ char *buffer;
+ bool finished;
+ int chunk_size;
+
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+
+private:
+ int putShort(char *t, unsigned int value);
+ int putLong(char *t, unsigned int value);
+ int fillData(char *start, int frequency, int seconds);
+};
+
+class AudioTest : public QMainWindow
+{
+ Q_OBJECT
+public:
+ AudioTest();
+ ~AudioTest();
+
+ QAudioDeviceId device;
+ Generator* gen;
+ QAudioOutput* audioOutput;
+ QIODevice* output;
+ QTimer* timer;
+ QAudioFormat settings;
+
+ bool pullMode;
+ char* buffer;
+
+ QPushButton* button;
+ QPushButton* button2;
+ QComboBox* deviceBox;
+
+private slots:
+ void status();
+ void writeMore();
+ void toggle();
+ void togglePlay();
+ void state(QAudio::State s);
+ void deviceChanged(int idx);
+};
+
diff --git a/examples/multimedia/audio/audiooutput/audiooutput.pro b/examples/multimedia/audio/audiooutput/audiooutput.pro
new file mode 100644
index 0000000..08f43ce
--- /dev/null
+++ b/examples/multimedia/audio/audiooutput/audiooutput.pro
@@ -0,0 +1,11 @@
+HEADERS = audiooutput.h
+SOURCES = audiooutput.cpp \
+ main.cpp
+
+QT += multimedia
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio/audiooutput
+sources.files = $$SOURCES *.h $$RESOURCES $$FORMS audiooutput.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/multimedia/audio/audiooutput
+INSTALLS += target sources
diff --git a/examples/multimedia/audio/audiooutput/main.cpp b/examples/multimedia/audio/audiooutput/main.cpp
new file mode 100644
index 0000000..fc319bd
--- /dev/null
+++ b/examples/multimedia/audio/audiooutput/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtGui>
+
+#include "audiooutput.h"
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Audio Output Test");
+
+ AudioTest audio;
+ audio.show();
+
+ return app.exec();
+}
diff --git a/examples/multimedia/multimedia.pro b/examples/multimedia/multimedia.pro
new file mode 100644
index 0000000..ac78b15
--- /dev/null
+++ b/examples/multimedia/multimedia.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+SUBDIRS = audio
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multimedia
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS multimedia.pro README
+sources.path = $$[QT_INSTALL_EXAMPLES]/multimedia
+INSTALLS += target sources
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 1bac953..a03a313 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -36,7 +36,7 @@ INCLUDEPATH = $$QMAKE_INCDIR_QT $$INCLUDEPATH #prepending prevents us from picki
win32:INCLUDEPATH += $$QMAKE_INCDIR_QT/ActiveQt
# As order does matter for static libs, we reorder the QT variable here
-TMPLIBS = webkit phonon dbus testlib script scripttools svg qt3support sql xmlpatterns xml egl opengl openvg gui network core
+TMPLIBS = multimedia webkit phonon dbus testlib script scripttools svg qt3support sql xmlpatterns xml egl opengl openvg gui network core
for(QTLIB, $$list($$TMPLIBS)) {
contains(QT, $$QTLIB): QT_ORDERED += $$QTLIB
}
@@ -152,6 +152,7 @@ for(QTLIB, $$list($$lower($$unique(QT)))) {
else:isEqual(QTLIB, dbus):qlib = QtDBus
else:isEqual(QTLIB, phonon):qlib = phonon
else:isEqual(QTLIB, webkit):qlib = QtWebKit
+ else:isEqual(QTLIB, multimedia):qlib = QtMultimedia
else:message("Unknown QT: $$QTLIB"):qlib =
!isEmpty(qlib) {
target_qt:isEqual(TARGET, qlib) {
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 18d5a9f..1711f16 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1173,6 +1173,11 @@ class QDataStream;
# else
# define Q_OPENGL_EXPORT Q_DECL_IMPORT
# endif
+# if defined(QT_BUILD_MULTIMEDIA_LIB)
+# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT
+# else
+# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT
+# endif
# if defined(QT_BUILD_OPENVG_LIB)
# define Q_OPENVG_EXPORT Q_DECL_EXPORT
# else
@@ -1217,6 +1222,7 @@ class QDataStream;
# define Q_SVG_EXPORT Q_DECL_IMPORT
# define Q_CANVAS_EXPORT Q_DECL_IMPORT
# define Q_OPENGL_EXPORT Q_DECL_IMPORT
+# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT
# define Q_OPENVG_EXPORT Q_DECL_IMPORT
# define Q_XML_EXPORT Q_DECL_IMPORT
# define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT
@@ -1243,6 +1249,7 @@ class QDataStream;
# define Q_NETWORK_EXPORT Q_DECL_EXPORT
# define Q_SVG_EXPORT Q_DECL_EXPORT
# define Q_OPENGL_EXPORT Q_DECL_EXPORT
+# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT
# define Q_OPENVG_EXPORT Q_DECL_EXPORT
# define Q_XML_EXPORT Q_DECL_EXPORT
# define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT
@@ -1256,6 +1263,7 @@ class QDataStream;
# define Q_NETWORK_EXPORT
# define Q_SVG_EXPORT
# define Q_OPENGL_EXPORT
+# define Q_MULTIMEDIA_EXPORT
# define Q_XML_EXPORT
# define Q_XMLPATTERNS_EXPORT
# define Q_SCRIPT_EXPORT
@@ -2305,12 +2313,14 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
#define QT_MODULE_DBUS 0x08000
#define QT_MODULE_SCRIPTTOOLS 0x10000
#define QT_MODULE_OPENVG 0x20000
+#define QT_MODULE_MULTIMEDIA 0x40000
/* Qt editions */
#define QT_EDITION_CONSOLE (QT_MODULE_CORE \
| QT_MODULE_NETWORK \
| QT_MODULE_SQL \
| QT_MODULE_SCRIPT \
+ | QT_MODULE_MULTIMEDIA \
| QT_MODULE_XML \
| QT_MODULE_XMLPATTERNS \
| QT_MODULE_TEST \
@@ -2326,6 +2336,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
| QT_MODULE_OPENGL \
| QT_MODULE_OPENVG \
| QT_MODULE_SQL \
+ | QT_MODULE_MULTIMEDIA \
| QT_MODULE_XML \
| QT_MODULE_XMLPATTERNS \
| QT_MODULE_SCRIPT \
@@ -2374,6 +2385,9 @@ QT_LICENSED_MODULE(OpenVG)
#if (QT_EDITION & QT_MODULE_SQL)
QT_LICENSED_MODULE(Sql)
#endif
+#if (QT_EDITION & QT_MODULE_MULTIMEDIA)
+QT_LICENSED_MODULE(Multimedia)
+#endif
#if (QT_EDITION & QT_MODULE_XML)
QT_LICENSED_MODULE(Xml)
#endif
diff --git a/src/multimedia/audio/audio.pri b/src/multimedia/audio/audio.pri
new file mode 100644
index 0000000..3ddb23b
--- /dev/null
+++ b/src/multimedia/audio/audio.pri
@@ -0,0 +1,56 @@
+HEADERS += $$PWD/qaudio.h \
+ $$PWD/qaudioformat.h \
+ $$PWD/qaudioinput.h \
+ $$PWD/qaudiooutput.h \
+ $$PWD/qaudiodeviceinfo.h \
+ $$PWD/qaudioengineplugin.h \
+ $$PWD/qaudioengine.h \
+ $$PWD/qaudiodevicefactory_p.h \
+ $$PWD/qaudiodeviceid.h \
+ $$PWD/qaudiodeviceid_p.h
+
+
+SOURCES += $$PWD/qaudio.cpp \
+ $$PWD/qaudioformat.cpp \
+ $$PWD/qaudiodeviceinfo.cpp \
+ $$PWD/qaudiooutput.cpp \
+ $$PWD/qaudioinput.cpp \
+ $$PWD/qaudioengineplugin.cpp \
+ $$PWD/qaudioengine.cpp \
+ $$PWD/qaudiodevicefactory.cpp \
+ $$PWD/qaudiodeviceid.cpp
+
+mac {
+ HEADERS += $$PWD/qaudioinput_mac_p.h \
+ $$PWD/qaudiooutput_mac_p.h \
+ $$PWD/qaudiodeviceinfo_mac_p.h \
+ $$PWD/qaudio_mac_p.h
+
+ SOURCES += $$PWD/qaudiodeviceinfo_mac_p.cpp \
+ $$PWD/qaudiooutput_mac_p.cpp \
+ $$PWD/qaudioinput_mac_p.cpp \
+ $$PWD/qaudio_mac.cpp
+
+ LIBS += -framework CoreAudio -framework AudioUnit -framework AudioToolbox
+
+} else:win32 {
+
+ HEADERS += $$PWD/qaudioinput_win32_p.h $$PWD/qaudiooutput_win32_p.h $$PWD/qaudiodeviceinfo_win32_p.h
+ SOURCES += $$PWD/qaudiodeviceinfo_win32_p.cpp \
+ $$PWD/qaudiooutput_win32_p.cpp \
+ $$PWD/qaudioinput_win32_p.cpp
+ !wince*:LIBS += -lwinmm
+ wince*:LIBS += -lcoredll
+
+} else:unix {
+ unix:contains(QT_CONFIG, alsa) {
+ linux-*|freebsd-*|openbsd-*:{
+ DEFINES += HAS_ALSA
+ HEADERS += $$PWD/qaudiooutput_alsa_p.h $$PWD/qaudioinput_alsa_p.h $$PWD/qaudiodeviceinfo_alsa_p.h
+ SOURCES += $$PWD/qaudiodeviceinfo_alsa_p.cpp \
+ $$PWD/qaudiooutput_alsa_p.cpp \
+ $$PWD/qaudioinput_alsa_p.cpp
+ LIBS += -lasound
+ }
+ }
+}
diff --git a/src/multimedia/audio/qaudio.cpp b/src/multimedia/audio/qaudio.cpp
new file mode 100644
index 0000000..5ba6493
--- /dev/null
+++ b/src/multimedia/audio/qaudio.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtMultimedia/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.
+ \since 4.6
+*/
+
+/*!
+ \enum QAudio::Error
+
+ \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
+
+ \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 SuspendState The audio device is in a suspended state, this state will only be entered
+ after suspend() is called.
+ \value StopState 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
+
+ \value AudioOutput audio output device
+ \value AudioInput audio input device
+*/
+
+
+QT_END_NAMESPACE
+
diff --git a/src/multimedia/audio/qaudio.h b/src/multimedia/audio/qaudio.h
new file mode 100644
index 0000000..b996cc6
--- /dev/null
+++ b/src/multimedia/audio/qaudio.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QAUDIO_H
+#define QAUDIO_H
+
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+namespace QAudio
+{
+ enum Error { NoError, OpenError, IOError, UnderrunError, FatalError };
+ enum State { ActiveState, SuspendState, StopState, 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
diff --git a/src/multimedia/audio/qaudio_mac.cpp b/src/multimedia/audio/qaudio_mac.cpp
new file mode 100644
index 0000000..cfa7ca3
--- /dev/null
+++ b/src/multimedia/audio/qaudio_mac.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 & kLinearPCMFormatFlagIsBigEndian != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian);
+ QAudioFormat::SampleType type = QAudioFormat::UnSignedInt;
+ if ((sf.mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) != 0)
+ type = QAudioFormat::SignedInt;
+ else if ((sf.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 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;
+ }
+
+ 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
+
+
diff --git a/src/multimedia/audio/qaudio_mac_p.h b/src/multimedia/audio/qaudio_mac_p.h
new file mode 100644
index 0000000..8e2d522
--- /dev/null
+++ b/src/multimedia/audio/qaudio_mac_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/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
+
+
diff --git a/src/multimedia/audio/qaudiodevicefactory.cpp b/src/multimedia/audio/qaudiodevicefactory.cpp
new file mode 100644
index 0000000..35e9c91
--- /dev/null
+++ b/src/multimedia/audio/qaudiodevicefactory.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdebug.h>
+#include <QtMultimedia/qaudioengine.h>
+#include <QtMultimedia/qaudioengineplugin.h>
+#include <private/qfactoryloader_p.h>
+#include "qaudiodevicefactory_p.h"
+#include "qaudiodeviceid_p.h"
+
+#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
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QAudioEngineFactoryInterface_iid, QLatin1String("/audio"), Qt::CaseInsensitive))
+
+
+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 codecList() { return QStringList(); }
+ QList<int> frequencyList() { return QList<int>(); }
+ QList<int> channelsList() { return QList<int>(); }
+ QList<int> sampleSizeList() { return QList<int>(); }
+ QList<QAudioFormat::Endian> byteOrderList() { return QList<QAudioFormat::Endian>(); }
+ QList<QAudioFormat::SampleType> sampleTypeList() { return QList<QAudioFormat::SampleType>(); }
+};
+
+class QNullInputDevice : public QAbstractAudioInput
+{
+public:
+ QIODevice* start(QIODevice* ) { 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 totalTime() const { return 0; }
+ qint64 clock() const { return 0; }
+ QAudio::Error error() const { return QAudio::OpenError; }
+ QAudio::State state() const { return QAudio::StopState; }
+ QAudioFormat format() const { return QAudioFormat(); }
+};
+
+class QNullOutputDevice : public QAbstractAudioOutput
+{
+public:
+ QIODevice* start(QIODevice* ) { 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 totalTime() const { return 0; }
+ qint64 clock() const { return 0; }
+ QAudio::Error error() const { return QAudio::OpenError; }
+ QAudio::State state() const { return QAudio::StopState; }
+ QAudioFormat format() const { return QAudioFormat(); }
+};
+
+QList<QAudioDeviceId> QAudioDeviceFactory::deviceList(QAudio::Mode mode)
+{
+ QList<QAudioDeviceId> devices;
+#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
+ foreach (const QByteArray &handle, QAudioDeviceInfoPrivate::deviceList(mode))
+ devices += createDeviceId(QLatin1String("builtin"), mode, handle);
+#endif
+ QFactoryLoader* l = loader();
+
+ foreach (QString const& key, l->keys()) {
+ QAudioEngineFactoryInterface* plugin = qobject_cast<QAudioEngineFactoryInterface*>(l->instance(key));
+ if (plugin) {
+ foreach (QByteArray const& handle, plugin->deviceList(mode))
+ devices += createDeviceId(key, mode, handle);
+ }
+
+ delete plugin;
+ }
+
+ return devices;
+}
+
+QAudioDeviceId QAudioDeviceFactory::defaultInputDevice()
+{
+ QAudioEngineFactoryInterface* plugin = qobject_cast<QAudioEngineFactoryInterface*>(loader()->instance(QLatin1String("default")));
+
+ if (plugin) {
+ QList<QByteArray> list = plugin->deviceList(QAudio::AudioInput);
+ if (list.size() > 0)
+ return createDeviceId(QLatin1String("default"), QAudio::AudioInput, list.at(0));
+ }
+#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
+ return createDeviceId(QLatin1String("builtin"), QAudio::AudioInput, QAudioDeviceInfoPrivate::defaultInputDevice());
+#endif
+ return QAudioDeviceId();
+}
+
+QAudioDeviceId QAudioDeviceFactory::defaultOutputDevice()
+{
+ QAudioEngineFactoryInterface* plugin = qobject_cast<QAudioEngineFactoryInterface*>(loader()->instance(QLatin1String("default")));
+
+ if (plugin) {
+ QList<QByteArray> list = plugin->deviceList(QAudio::AudioOutput);
+ if (list.size() > 0)
+ return createDeviceId(QLatin1String("default"), QAudio::AudioOutput, list.at(0));
+ }
+#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
+ return createDeviceId(QLatin1String("builtin"), QAudio::AudioOutput, QAudioDeviceInfoPrivate::defaultOutputDevice());
+#endif
+ return QAudioDeviceId();
+}
+
+QAbstractAudioDeviceInfo* QAudioDeviceFactory::audioDeviceInfo(QAudioDeviceId const& id)
+{
+ if (id.isNull())
+ return new QNullDeviceInfo();
+#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
+ if (id.d->key == QLatin1String("builtin"))
+ return new QAudioDeviceInfoPrivate(id.d->handle, QAudio::Mode(id.d->mode));
+#endif
+ QAudioEngineFactoryInterface* plugin = qobject_cast<QAudioEngineFactoryInterface*>(loader()->instance(id.d->key));
+
+ if (plugin)
+ return plugin->createDeviceInfo(id.d->handle, QAudio::Mode(id.d->mode));
+
+ return new QNullDeviceInfo();
+}
+
+QAbstractAudioInput* QAudioDeviceFactory::createDefaultInputDevice(QAudioFormat const &format)
+{
+ return createInputDevice(defaultInputDevice(), format);
+}
+
+QAbstractAudioOutput* QAudioDeviceFactory::createDefaultOutputDevice(QAudioFormat const &format)
+{
+ return createOutputDevice(defaultOutputDevice(), format);
+}
+
+QAbstractAudioInput* QAudioDeviceFactory::createInputDevice(QAudioDeviceId const& id, QAudioFormat const &format)
+{
+ if (id.isNull())
+ return new QNullInputDevice();
+#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
+ if (id.d->key == QLatin1String("builtin")) {
+ if(!defaultInputDevice().isNull())
+ return new QAudioInputPrivate(id.d->handle, format);
+ else
+ return new QNullInputDevice();
+ }
+#endif
+ QAudioEngineFactoryInterface* plugin = qobject_cast<QAudioEngineFactoryInterface*>(loader()->instance((id.d->key)));
+
+ if (plugin)
+ return plugin->createInput(id.d->handle, format);
+
+ return new QNullInputDevice();
+}
+
+QAbstractAudioOutput* QAudioDeviceFactory::createOutputDevice(QAudioDeviceId const& id, QAudioFormat const &format)
+{
+ if (id.isNull())
+ return new QNullOutputDevice();
+#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA))
+ if (id.d->key == QLatin1String("builtin")) {
+ if(!defaultOutputDevice().isNull())
+ return new QAudioOutputPrivate(id.d->handle, format);
+ else
+ return new QNullOutputDevice();
+ }
+#endif
+ QAudioEngineFactoryInterface* plugin = qobject_cast<QAudioEngineFactoryInterface*>(loader()->instance(id.d->key));
+
+ if (plugin)
+ return plugin->createOutput(id.d->handle, format);
+
+ return new QNullOutputDevice();
+}
+
+QAudioDeviceId QAudioDeviceFactory::createDeviceId(QString const& key, int mode, QByteArray const& handle)
+{
+ return QAudioDeviceId(new QAudioDeviceIdPrivate(key, mode, handle));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/multimedia/audio/qaudiodevicefactory_p.h b/src/multimedia/audio/qaudiodevicefactory_p.h
new file mode 100644
index 0000000..a8e2b28
--- /dev/null
+++ b/src/multimedia/audio/qaudiodevicefactory_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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/qglobal.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+
+#include <QtMultimedia/qaudiodeviceid.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+class QAbstractAudioInput;
+class QAbstractAudioOutput;
+
+
+class QAudioDeviceFactory
+{
+public:
+ static QList<QAudioDeviceId> deviceList(QAudio::Mode mode);
+
+ static QAudioDeviceId defaultInputDevice();
+ static QAudioDeviceId defaultOutputDevice();
+
+ static QAbstractAudioDeviceInfo* audioDeviceInfo(QAudioDeviceId const &device);
+
+ static QAbstractAudioInput* createDefaultInputDevice(QAudioFormat const &format);
+ static QAbstractAudioOutput* createDefaultOutputDevice(QAudioFormat const &format);
+
+ static QAbstractAudioInput* createInputDevice(QAudioDeviceId const &device, QAudioFormat const &format);
+ static QAbstractAudioOutput* createOutputDevice(QAudioDeviceId const &device, QAudioFormat const &format);
+
+ static QAbstractAudioInput* createNullInput();
+ static QAbstractAudioOutput* createNullOutput();
+
+ static QAudioDeviceId createDeviceId(QString const& key, int mode, QByteArray const& handle);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAUDIODEVICEFACTORY_P_H
+
diff --git a/src/multimedia/audio/qaudiodeviceid.cpp b/src/multimedia/audio/qaudiodeviceid.cpp
new file mode 100644
index 0000000..21a9cd8
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceid.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qdatastream.h>
+
+#include <QtMultimedia/qaudiodeviceid.h>
+#include "qaudiodeviceid_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAudioDeviceId
+ \brief The QAudioDeviceId class provides means for identifying a unique input or output device on a system.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia
+ \since 4.6
+
+ \sa QAudioDeviceInfo, QAudioOutput, QAudioInput
+*/
+
+/*!
+ Construct a new null QAudioDeviceId.
+*/
+
+QAudioDeviceId::QAudioDeviceId()
+{
+}
+
+/*!
+ Copy the QAudDeviceId referenced by \a other.
+*/
+
+QAudioDeviceId::QAudioDeviceId(const QAudioDeviceId &other):
+ d(other.d)
+{
+}
+
+/*!
+ Destroy the QAudioDeviceId.
+*/
+
+QAudioDeviceId::~QAudioDeviceId()
+{
+}
+
+/*!
+ Make a copy of the \a other QAudioDeviceId.
+*/
+
+QAudioDeviceId& QAudioDeviceId::operator=(const QAudioDeviceId &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Compare with the \a other QAudioDeviceId, return true if they are the same;
+ otherwise false.
+*/
+
+bool QAudioDeviceId::operator==(const QAudioDeviceId &other) const
+{
+ return (d.constData() == 0 && other.d.constData() == 0) ||
+ (d.constData() != 0 && other.d.constData() != 0 &&
+ d->key == other.d->key && d->mode == other.d->mode && d->handle == other.d->handle);
+}
+
+/*!
+ Compare with the \a other QAudioDeviceId, return false if they are the same;
+ otherwise true.
+*/
+
+bool QAudioDeviceId::operator!=(const QAudioDeviceId &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Returns true if this is not a valid QAudioDeviceId; otherwise false.
+*/
+
+bool QAudioDeviceId::isNull() const
+{
+ return d.constData() == 0;
+}
+
+/*!
+ \internal
+*/
+
+QAudioDeviceId::QAudioDeviceId(QAudioDeviceIdPrivate* data):
+ d(data)
+{
+}
+
+/*!
+ \internal
+*/
+
+QAudioDeviceIdPrivate::QAudioDeviceIdPrivate(QString const& k, int m, QByteArray const& h):
+ key(k), mode(m), handle(h)
+{
+}
+
+#ifndef QT_NO_DATASTREAM
+Q_MULTIMEDIA_EXPORT QDataStream &operator<<(QDataStream &s, const QAudioDeviceId &id)
+{
+ s << id.d->key << id.d->mode << id.d->handle;
+ return s;
+}
+
+Q_MULTIMEDIA_EXPORT QDataStream &operator>>(QDataStream &s, QAudioDeviceId &id)
+{
+ QString key;
+ int mode;
+ QByteArray handle;
+
+ s >> key >> mode >> handle;
+ id = QAudioDeviceId(new QAudioDeviceIdPrivate(key, mode, handle));
+
+ return s;
+}
+#endif
+
+
+QT_END_NAMESPACE
diff --git a/src/multimedia/audio/qaudiodeviceid.h b/src/multimedia/audio/qaudiodeviceid.h
new file mode 100644
index 0000000..f9188d3
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceid.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAUDIODEVICEID_H
+#define QAUDIODEVICEID_H
+
+#include <QtCore/qshareddata.h>
+#include <QtCore/qmetatype.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QAudioDeviceFactory;
+class QAudioDeviceIdPrivate;
+
+class Q_MULTIMEDIA_EXPORT QAudioDeviceId
+{
+ friend class QAudioDeviceFactory;
+ friend Q_MULTIMEDIA_EXPORT QDataStream &operator<<(QDataStream&, const QAudioDeviceId&);
+ friend Q_MULTIMEDIA_EXPORT QDataStream &operator>>(QDataStream&, QAudioDeviceId&);
+
+public:
+ QAudioDeviceId();
+ QAudioDeviceId(const QAudioDeviceId &other);
+ ~QAudioDeviceId();
+
+ QAudioDeviceId& operator=(const QAudioDeviceId &other);
+ bool operator==(const QAudioDeviceId &id) const;
+ bool operator!=(const QAudioDeviceId &id) const;
+
+ bool isNull() const;
+
+private:
+ QAudioDeviceId(QAudioDeviceIdPrivate *data);
+
+ QSharedDataPointer<QAudioDeviceIdPrivate> d;
+};
+
+#ifndef QT_NO_DATASTREAM
+Q_MULTIMEDIA_EXPORT QDataStream &operator<<(QDataStream&, const QAudioDeviceId&);
+Q_MULTIMEDIA_EXPORT QDataStream &operator>>(QDataStream&, QAudioDeviceId&);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+Q_DECLARE_METATYPE(QAudioDeviceId);
+
+
+#endif // QAUDIODEVICEID_H
diff --git a/src/multimedia/audio/qaudiodeviceid_p.h b/src/multimedia/audio/qaudiodeviceid_p.h
new file mode 100644
index 0000000..3034574
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceid_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 QAUDIODEVICEIDPRIVATE_H
+#define QAUDIODEVICEIDPRIVATE_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QAudioDeviceIdPrivate : public QSharedData
+{
+public:
+ QAudioDeviceIdPrivate(QString const& k, int m, QByteArray const& h);
+
+ QString key;
+ int mode;
+ QByteArray handle;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAUDIODEVICEIDPRIVATE_H
diff --git a/src/multimedia/audio/qaudiodeviceinfo.cpp b/src/multimedia/audio/qaudiodeviceinfo.cpp
new file mode 100644
index 0000000..c1895d7
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaudiodevicefactory_p.h"
+#include <QtMultimedia/qaudioengine.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAudioDeviceInfo
+ \brief The QAudioDeviceInfo class provides an interface to query audio devices and their functionality.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia
+ \since 4.6
+
+ 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.
+
+ 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(), supportedChannels(), supportedCodecs(),
+ supportedFrequencies(), 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().
+
+ A QAudioDeviceInfo is constructed with a QAudioDeviceId, which is
+ an identifier for a physical device. It is used by Qt to construct
+ classes that communicate with the device--such as
+ QAudioDeviceInfo, QAudioInput, and QAudioOutput. The static
+ functions defaultInputDevice(), defaultOutputDevice(), and
+ deviceList() let you get a hold of the ids for all available
+ devices. You fetch ids based on whether you will use the device
+ for input or output; this is specified by the QAudio::Mode enum.
+ The QAudioDeviceId returned are only valid for the QAudio::Mode.
+
+ For instance:
+
+ \code
+ foreach(QAudioDeviceId audioId, QAudioDeviceInfo::deviceList(QAudio::AudioOutput)) {
+ QAudioDeviceInfo info(audioId);
+ qDebug() << "Device name: " << info.deviceName();
+ }
+ \endcode
+
+ 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, QAudioDeviceId
+*/
+
+/*!
+ Construct a new audio device info and attach it to \a parent.
+ Using the audio device with the specified \a id.
+*/
+
+QAudioDeviceInfo::QAudioDeviceInfo(const QAudioDeviceId &id, QObject *parent):
+ QObject(parent)
+{
+ d = QAudioDeviceFactory::audioDeviceInfo(id);
+}
+
+/*!
+ Destroy this audio device info.
+*/
+
+QAudioDeviceInfo::~QAudioDeviceInfo()
+{
+ delete d;
+}
+
+/*!
+ Returns human readable name of audio device.
+
+ Device names vary depending on platform/audio plugin being used.
+
+ They are a unique string identifiers for the audio device.
+
+ eg. default, Intel, U0x46d0x9a4
+*/
+
+QString QAudioDeviceInfo::deviceName() const
+{
+ return d->deviceName();
+}
+
+/*!
+ Returns true if \a settings are supported by the audio device of this QAudioDeviceInfo.
+*/
+
+bool QAudioDeviceInfo::isFormatSupported(const QAudioFormat &settings) const
+{
+ return d->isFormatSupported(settings);
+}
+
+/*!
+ Returns QAudioFormat of default settings.
+
+ These settings are provided by the platform/audio plugin being used.
+
+ They also are dependent on the 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
+*/
+
+QAudioFormat QAudioDeviceInfo::preferredFormat() const
+{
+ return d->preferredFormat();
+}
+
+/*!
+ Returns closest QAudioFormat to \a settings that system audio supports.
+
+ These settings are provided by the platform/audio plugin being used.
+
+ They also are dependent on the QAudio::Mode being used.
+*/
+
+QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const
+{
+ return d->nearestFormat(settings);
+}
+
+/*!
+ 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/
+*/
+
+QStringList QAudioDeviceInfo::supportedCodecs() const
+{
+ return d->codecList();
+}
+
+/*!
+ Returns a list of supported frequencies.
+*/
+
+QList<int> QAudioDeviceInfo::supportedFrequencies() const
+{
+ return d->frequencyList();
+}
+
+/*!
+ Returns a list of supported channels.
+*/
+
+QList<int> QAudioDeviceInfo::supportedChannels() const
+{
+ return d->channelsList();
+}
+
+/*!
+ Returns a list of supported sample sizes.
+*/
+
+QList<int> QAudioDeviceInfo::supportedSampleSizes() const
+{
+ return d->sampleSizeList();
+}
+
+/*!
+ Returns a list of supported byte orders.
+*/
+
+QList<QAudioFormat::Endian> QAudioDeviceInfo::supportedByteOrders() const
+{
+ return d->byteOrderList();
+}
+
+/*!
+ Returns a list of supported sample types.
+*/
+
+QList<QAudioFormat::SampleType> QAudioDeviceInfo::supportedSampleTypes() const
+{
+ return d->sampleTypeList();
+}
+
+/*!
+ Returns the name of the default input audio device.
+ All platform and audio plugin implementations provide a default audio device to use.
+*/
+
+QAudioDeviceId QAudioDeviceInfo::defaultInputDevice()
+{
+ return QAudioDeviceFactory::defaultInputDevice();
+}
+
+/*!
+ Returns the name of the default output audio device.
+ All platform and audio plugin implementations provide a default audio device to use.
+*/
+
+QAudioDeviceId QAudioDeviceInfo::defaultOutputDevice()
+{
+ return QAudioDeviceFactory::defaultOutputDevice();
+}
+
+/*!
+ Returns a list of audio devices that support \a mode.
+*/
+
+QList<QAudioDeviceId> QAudioDeviceInfo::deviceList(QAudio::Mode mode)
+{
+ return QAudioDeviceFactory::deviceList(mode);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/multimedia/audio/qaudiodeviceinfo.h b/src/multimedia/audio/qaudiodeviceinfo.h
new file mode 100644
index 0000000..444a00a
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QAUDIODEVICEINFO_H
+#define QAUDIODEVICEINFO_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qlist.h>
+
+#include <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qaudiodeviceid.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+
+class QAbstractAudioDeviceInfo;
+
+class Q_MULTIMEDIA_EXPORT QAudioDeviceInfo : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QAudioDeviceInfo(const QAudioDeviceId &id, QObject *parent = 0);
+ ~QAudioDeviceInfo();
+
+ 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> supportedChannels() const;
+ QList<int> supportedSampleSizes() const;
+ QList<QAudioFormat::Endian> supportedByteOrders() const;
+ QList<QAudioFormat::SampleType> supportedSampleTypes() const;
+
+ static QAudioDeviceId defaultInputDevice();
+ static QAudioDeviceId defaultOutputDevice();
+
+ static QList<QAudioDeviceId> deviceList(QAudio::Mode mode);
+
+private:
+ Q_DISABLE_COPY(QAudioDeviceInfo)
+
+ QAbstractAudioDeviceInfo* d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAUDIODEVICEINFO_H
diff --git a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp
new file mode 100644
index 0000000..fe45f82
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#include "qaudiodeviceinfo_alsa_p.h"
+
+QAudioDeviceInfoPrivate::QAudioDeviceInfoPrivate(QByteArray dev, QAudio::Mode mode)
+{
+ handle = 0;
+
+ device = QLatin1String(dev);
+ this->mode = mode;
+}
+
+QAudioDeviceInfoPrivate::~QAudioDeviceInfoPrivate()
+{
+ close();
+}
+
+bool QAudioDeviceInfoPrivate::isFormatSupported(const QAudioFormat& format) const
+{
+ return testSettings(format);
+}
+
+QAudioFormat QAudioDeviceInfoPrivate::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(tr("audio/pcm"));
+ } else {
+ nearest.setFrequency(8000);
+ nearest.setChannels(1);
+ nearest.setSampleType(QAudioFormat::SignedInt);
+ nearest.setSampleSize(8);
+ nearest.setCodec(tr("audio/pcm"));
+ }
+ return nearest;
+}
+
+QAudioFormat QAudioDeviceInfoPrivate::nearestFormat(const QAudioFormat& format) const
+{
+ if(testSettings(format))
+ return format;
+ else
+ return preferredFormat();
+}
+
+QString QAudioDeviceInfoPrivate::deviceName() const
+{
+ return device;
+}
+
+QStringList QAudioDeviceInfoPrivate::codecList()
+{
+ updateLists();
+ return codecz;
+}
+
+QList<int> QAudioDeviceInfoPrivate::frequencyList()
+{
+ updateLists();
+ return freqz;
+}
+
+QList<int> QAudioDeviceInfoPrivate::channelsList()
+{
+ updateLists();
+ return channelz;
+}
+
+QList<int> QAudioDeviceInfoPrivate::sampleSizeList()
+{
+ updateLists();
+ return sizez;
+}
+
+QList<QAudioFormat::Endian> QAudioDeviceInfoPrivate::byteOrderList()
+{
+ updateLists();
+ return byteOrderz;
+}
+
+QList<QAudioFormat::SampleType> QAudioDeviceInfoPrivate::sampleTypeList()
+{
+ updateLists();
+ return typez;
+}
+
+bool QAudioDeviceInfoPrivate::open()
+{
+ int err = 0;
+ QString dev = device;
+ if(!dev.contains(tr("default"))) {
+ int idx = snd_card_get_index(dev.toLocal8Bit().constData());
+ dev = QString(tr("hw:%1,0")).arg(idx);
+ }
+ 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 QAudioDeviceInfoPrivate::close()
+{
+ if(handle)
+ snd_pcm_close(handle);
+ handle = 0;
+}
+
+bool QAudioDeviceInfoPrivate::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;
+
+ // open()
+ if(!dev.contains(tr("default"))) {
+ int idx = snd_card_get_index(dev.toLocal8Bit().constData());
+ dev = QString(tr("hw:%1,0")).arg(idx);
+ }
+ if(mode == QAudio::AudioOutput) {
+ err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
+ } else {
+ err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
+ }
+ if(err < 0) {
+ handle = 0;
+ return false;
+ }
+
+ bool testChannel = false;
+ bool testCodec = false;
+ bool testFreq = false;
+ bool testType = false;
+ bool testSize = false;
+
+ int dir = 0;
+
+ snd_pcm_nonblock( handle, 0 );
+ snd_pcm_hw_params_alloca( &params );
+ snd_pcm_hw_params_any( handle, params );
+
+ // For now, just accept only audio/pcm codec
+ if(!format.codec().startsWith(tr("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 QAudioDeviceInfoPrivate::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);
+ 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(tr("audio/pcm"));
+ close();
+}
+
+QList<QByteArray> QAudioDeviceInfoPrivate::deviceList(QAudio::Mode mode)
+{
+ QAudio::Mode _m;
+ QList<QByteArray> devices;
+ QByteArray filter;
+ QString dir;
+
+ // 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;
+
+ while (*n != NULL) {
+ _m = QAudio::AudioOutput;
+ name = snd_device_name_get_hint(*n, "NAME");
+ descr = snd_device_name_get_hint(*n, "DESC");
+ io = snd_device_name_get_hint(*n, "IOID");
+ dir = QString::fromUtf8(io);
+ if((name != NULL) && (descr != NULL) && ((io == NULL) || (dir.length() ==filter.length()))) {
+ if(dir.length() == 5)
+ _m = QAudio::AudioInput;
+ if(io == NULL)
+ _m = mode;
+
+ QString str = tr(name);
+
+ if(str.contains(tr("default"))) {
+ int pos = str.indexOf(tr("="),0);
+ devices.append(str.mid(pos+1).toLocal8Bit().constData());
+ }
+ }
+ if(name != NULL)
+ 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");
+ if(mode == QAudio::AudioInput) {
+ filter.append("Input");
+ } else {
+ filter.append("Output");
+ }
+ }
+
+ return devices;
+}
+
+QByteArray QAudioDeviceInfoPrivate::defaultInputDevice()
+{
+ QList<QByteArray> devices = deviceList(QAudio::AudioInput);
+ if(devices.size() == 0)
+ return QByteArray();
+
+ return QByteArray("default");
+}
+
+QByteArray QAudioDeviceInfoPrivate::defaultOutputDevice()
+{
+ QList<QByteArray> devices = deviceList(QAudio::AudioOutput);
+ if(devices.size() == 0)
+ return QByteArray();
+
+ return QByteArray("default");
+}
+
+
diff --git a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.h b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.h
new file mode 100644
index 0000000..3ac9239
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+const unsigned int MAX_SAMPLE_RATES = 5;
+const unsigned int SAMPLE_RATES[] =
+ { 8000, 11025, 22050, 44100, 48000 };
+
+class QAudioDeviceInfoPrivate : public QAbstractAudioDeviceInfo
+{
+ Q_OBJECT
+public:
+ QAudioDeviceInfoPrivate(QByteArray dev,QAudio::Mode mode);
+ ~QAudioDeviceInfoPrivate();
+
+ bool testSettings(const QAudioFormat& format) const;
+ void updateLists();
+ QAudioFormat preferredFormat() const;
+ bool isFormatSupported(const QAudioFormat& format) const;
+ QAudioFormat nearestFormat(const QAudioFormat& format) const;
+ QString deviceName() const;
+ QStringList codecList();
+ QList<int> frequencyList();
+ QList<int> channelsList();
+ QList<int> sampleSizeList();
+ QList<QAudioFormat::Endian> byteOrderList();
+ QList<QAudioFormat::SampleType> sampleTypeList();
+ static QByteArray defaultInputDevice();
+ static QByteArray defaultOutputDevice();
+ static QList<QByteArray> deviceList(QAudio::Mode);
+
+private:
+ bool open();
+ void close();
+
+ 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;
+};
+
+#endif
+
diff --git a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp
new file mode 100644
index 0000000..c94e0c4
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qdebug.h>
+#include <private/qcore_mac_p.h>
+
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include "qaudio_mac_p.h"
+#include "qaudiodeviceinfo_mac_p.h"
+
+
+
+QT_BEGIN_NAMESPACE
+
+
+QAudioDeviceInfoPrivate::QAudioDeviceInfoPrivate(QByteArray const& handle, QAudio::Mode)
+{
+ QDataStream ds(handle);
+ quint32 did, tm;
+
+ ds >> did >> tm >> name;
+ deviceId = AudioDeviceID(did);
+ mode = QAudio::Mode(tm);
+}
+
+bool QAudioDeviceInfoPrivate::isFormatSupported(const QAudioFormat& format) const
+{
+ return format.codec() == QString::fromLatin1("audio/pcm");
+}
+
+QAudioFormat QAudioDeviceInfoPrivate::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;
+}
+
+QAudioFormat QAudioDeviceInfoPrivate::nearestFormat(const QAudioFormat& format) const
+{
+ QAudioFormat rc(format);
+ QAudioFormat target = preferredFormat();
+
+ if (!format.codec().isEmpty() && format.codec() != QString::fromLatin1("audio/pcm"))
+ return QAudioFormat();
+
+ rc.setCodec(QString::fromLatin1("audio/pcm"));
+
+ if (rc.frequency() != target.frequency())
+ rc.setFrequency(target.frequency());
+ if (rc.channels() != target.channels())
+ rc.setChannels(target.channels());
+ if (rc.sampleSize() != target.sampleSize())
+ rc.setSampleSize(target.sampleSize());
+ if (rc.byteOrder() != target.byteOrder())
+ rc.setByteOrder(target.byteOrder());
+ if (rc.sampleType() != target.sampleType())
+ rc.setSampleType(target.sampleType());
+
+ return rc;
+}
+
+QString QAudioDeviceInfoPrivate::deviceName() const
+{
+ return name;
+}
+
+QStringList QAudioDeviceInfoPrivate::codecList()
+{
+ return QStringList() << QString::fromLatin1("audio/pcm");
+}
+
+QList<int> QAudioDeviceInfoPrivate::frequencyList()
+{
+ 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> QAudioDeviceInfoPrivate::channelsList()
+{
+ 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> QAudioDeviceInfoPrivate::sampleSizeList()
+{
+ return QList<int>() << 8 << 16 << 24 << 32 << 64;
+}
+
+QList<QAudioFormat::Endian> QAudioDeviceInfoPrivate::byteOrderList()
+{
+ return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian;
+}
+
+QList<QAudioFormat::SampleType> QAudioDeviceInfoPrivate::sampleTypeList()
+{
+ 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";
+ }
+ ds << QCFString::toQString(name);
+
+ CFRelease(name);
+
+ return device;
+}
+
+QByteArray QAudioDeviceInfoPrivate::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 QAudioDeviceInfoPrivate::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> QAudioDeviceInfoPrivate::deviceList(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
+
diff --git a/src/multimedia/audio/qaudiodeviceinfo_mac_p.h b/src/multimedia/audio/qaudiodeviceinfo_mac_p.h
new file mode 100644
index 0000000..ee593de
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo_mac_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudioengine.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QAudioDeviceInfoPrivate : public QAbstractAudioDeviceInfo
+{
+public:
+ AudioDeviceID deviceId;
+ QString name;
+ QAudio::Mode mode;
+
+ QAudioDeviceInfoPrivate(QByteArray const& handle, QAudio::Mode mode);
+
+ bool isFormatSupported(const QAudioFormat& format) const;
+ QAudioFormat preferredFormat() const;
+ QAudioFormat nearestFormat(const QAudioFormat& format) const;
+
+ QString deviceName() const;
+
+ QStringList codecList();
+ QList<int> frequencyList();
+ QList<int> channelsList();
+ QList<int> sampleSizeList();
+ QList<QAudioFormat::Endian> byteOrderList();
+ QList<QAudioFormat::SampleType> sampleTypeList();
+
+ static QByteArray defaultInputDevice();
+ static QByteArray defaultOutputDevice();
+
+ static QList<QByteArray> deviceList(QAudio::Mode mode);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDEVICEINFO_MAC_P_H
diff --git a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp
new file mode 100644
index 0000000..1a1995a
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp
@@ -0,0 +1,378 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+
+#include <windows.h>
+#include <mmsystem.h>
+#include "qaudiodeviceinfo_win32_p.h"
+
+// 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
+
+
+QAudioDeviceInfoPrivate::QAudioDeviceInfoPrivate(QByteArray dev, QAudio::Mode mode)
+{
+ device = QLatin1String(dev);
+ this->mode = mode;
+}
+
+QAudioDeviceInfoPrivate::~QAudioDeviceInfoPrivate()
+{
+ close();
+}
+
+bool QAudioDeviceInfoPrivate::isFormatSupported(const QAudioFormat& format) const
+{
+ return testSettings(format);
+}
+
+QAudioFormat QAudioDeviceInfoPrivate::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(tr("audio/pcm"));
+ } else {
+ nearest.setFrequency(11025);
+ nearest.setChannels(1);
+ nearest.setSampleType(QAudioFormat::SignedInt);
+ nearest.setSampleSize(8);
+ nearest.setCodec(tr("audio/pcm"));
+ }
+ return nearest;
+}
+
+QAudioFormat QAudioDeviceInfoPrivate::nearestFormat(const QAudioFormat& format) const
+{
+ if(testSettings(format))
+ return format;
+ else
+ return preferredFormat();
+}
+
+QString QAudioDeviceInfoPrivate::deviceName() const
+{
+ return device;
+}
+
+QStringList QAudioDeviceInfoPrivate::codecList()
+{
+ updateLists();
+ return codecz;
+}
+
+QList<int> QAudioDeviceInfoPrivate::frequencyList()
+{
+ updateLists();
+ return freqz;
+}
+
+QList<int> QAudioDeviceInfoPrivate::channelsList()
+{
+ updateLists();
+ return channelz;
+}
+
+QList<int> QAudioDeviceInfoPrivate::sampleSizeList()
+{
+ updateLists();
+ return sizez;
+}
+
+QList<QAudioFormat::Endian> QAudioDeviceInfoPrivate::byteOrderList()
+{
+ updateLists();
+ return byteOrderz;
+}
+
+QList<QAudioFormat::SampleType> QAudioDeviceInfoPrivate::sampleTypeList()
+{
+ updateLists();
+ return typez;
+}
+
+
+bool QAudioDeviceInfoPrivate::open()
+{
+ return true;
+}
+
+void QAudioDeviceInfoPrivate::close()
+{
+}
+
+bool QAudioDeviceInfoPrivate::testSettings(const QAudioFormat& format) const
+{
+ // Set nearest to closest settings that do work.
+ // See if what is in settings will work (return value).
+
+ bool testChannel = false;
+ bool testCodec = false;
+ bool testFreq = false;
+
+ int err = 0;
+
+ // For now, just accept only audio/pcm codec
+ if(!format.codec().startsWith(tr("audio/pcm"))) {
+ err=-1;
+ } else
+ testCodec = true;
+
+ if(err>=0 && format.channels() != -1) {
+ testChannel = true;
+ }
+
+ if(err>=0 && format.frequency() != -1) {
+ testFreq = true;
+ }
+
+ if(err == 0) {
+ // settings work
+ return true;
+ }
+ return false;
+}
+
+void QAudioDeviceInfoPrivate::updateLists()
+{
+ // redo all lists based on current settings
+ bool base = false;
+ bool match = false;
+ DWORD fmt = NULL;
+ QString tmp;
+
+ if(device.compare(tr("default")) == 0)
+ base = true;
+
+ if(mode == QAudio::AudioOutput) {
+ WAVEOUTCAPS woc;
+ unsigned long iNumDevs,i;
+ iNumDevs = waveOutGetNumDevs();
+ for(i=0;i<iNumDevs;i++) {
+ if(waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS))
+ == MMSYSERR_NOERROR) {
+ tmp = QString::fromUtf16((const unsigned short*)woc.szPname);
+ if(tmp.compare(device) == 0) {
+ match = true;
+ fmt = woc.dwFormats;
+ break;
+ }
+ if(base) {
+ match = true;
+ fmt = woc.dwFormats;
+ break;
+ }
+ }
+ }
+ } else {
+ WAVEINCAPS woc;
+ unsigned long iNumDevs,i;
+ iNumDevs = waveInGetNumDevs();
+ for(i=0;i<iNumDevs;i++) {
+ if(waveInGetDevCaps(i, &woc, sizeof(WAVEINCAPS))
+ == MMSYSERR_NOERROR) {
+ tmp = QString::fromUtf16((const unsigned short*)woc.szPname);
+ if(tmp.compare(device) == 0) {
+ match = true;
+ fmt = woc.dwFormats;
+ break;
+ }
+ if(base) {
+ match = true;
+ fmt = woc.dwFormats;
+ break;
+ }
+ }
+ }
+ }
+ 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)
+#ifndef Q_OS_WINCE
+ || (fmt && WAVE_FORMAT_48M08)
+ || (fmt && WAVE_FORMAT_48S08)
+ || (fmt && WAVE_FORMAT_96M08)
+ || (fmt && WAVE_FORMAT_96S08)
+#endif
+ ) {
+ 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)
+#ifndef Q_OS_WINCE
+ || (fmt && WAVE_FORMAT_48M16)
+ || (fmt && WAVE_FORMAT_48S16)
+ || (fmt && WAVE_FORMAT_96M16)
+ || (fmt && WAVE_FORMAT_96S16)
+#endif
+ ) {
+ 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);
+ }
+#ifndef Q_OS_WINCE
+ 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);
+ }
+#endif
+ channelz.append(1);
+ channelz.append(2);
+
+ byteOrderz.append(QAudioFormat::LittleEndian);
+
+ typez.append(QAudioFormat::SignedInt);
+ typez.append(QAudioFormat::UnSignedInt);
+
+ codecz.append(tr("audio/pcm"));
+ }
+}
+
+QList<QByteArray> QAudioDeviceInfoPrivate::deviceList(QAudio::Mode mode)
+{
+ Q_UNUSED(mode)
+
+ QList<QByteArray> devices;
+
+ devices.append("default");
+
+ if(mode == QAudio::AudioOutput) {
+ WAVEOUTCAPS woc;
+ unsigned long iNumDevs,i;
+ iNumDevs = waveOutGetNumDevs();
+ for(i=0;i<iNumDevs;i++) {
+ if(waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS))
+ == MMSYSERR_NOERROR) {
+ devices.append(QString::fromUtf16((const unsigned short*)woc.szPname).toLocal8Bit().constData());
+ }
+ }
+ } else {
+ WAVEINCAPS woc;
+ unsigned long iNumDevs,i;
+ iNumDevs = waveInGetNumDevs();
+ for(i=0;i<iNumDevs;i++) {
+ if(waveInGetDevCaps(i, &woc, sizeof(WAVEINCAPS))
+ == MMSYSERR_NOERROR) {
+ devices.append(QString::fromUtf16((const unsigned short*)woc.szPname).toLocal8Bit().constData());
+ }
+ }
+
+ }
+ return devices;
+}
+
+QByteArray QAudioDeviceInfoPrivate::defaultOutputDevice()
+{
+ return QByteArray("default");
+}
+
+QByteArray QAudioDeviceInfoPrivate::defaultInputDevice()
+{
+ return QByteArray("default");
+}
+
diff --git a/src/multimedia/audio/qaudiodeviceinfo_win32_p.h b/src/multimedia/audio/qaudiodeviceinfo_win32_p.h
new file mode 100644
index 0000000..140a741
--- /dev/null
+++ b/src/multimedia/audio/qaudiodeviceinfo_win32_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+
+const unsigned int MAX_SAMPLE_RATES = 5;
+const unsigned int SAMPLE_RATES[] = { 8000, 11025, 22050, 44100, 48000 };
+
+class QAudioDeviceInfoPrivate : public QAbstractAudioDeviceInfo
+{
+ Q_OBJECT
+
+public:
+ QAudioDeviceInfoPrivate(QByteArray dev,QAudio::Mode mode);
+ ~QAudioDeviceInfoPrivate();
+
+ bool open();
+ void close();
+
+ bool testSettings(const QAudioFormat& format) const;
+ void updateLists();
+ QAudioFormat preferredFormat() const;
+ bool isFormatSupported(const QAudioFormat& format) const;
+ QAudioFormat nearestFormat(const QAudioFormat& format) const;
+ QString deviceName() const;
+ QStringList codecList();
+ QList<int> frequencyList();
+ QList<int> channelsList();
+ QList<int> sampleSizeList();
+ QList<QAudioFormat::Endian> byteOrderList();
+ QList<QAudioFormat::SampleType> sampleTypeList();
+ static QByteArray defaultInputDevice();
+ static QByteArray defaultOutputDevice();
+ static QList<QByteArray> deviceList(QAudio::Mode);
+
+private:
+ QAudio::Mode mode;
+ QString device;
+ QAudioFormat nearest;
+ QList<int> freqz;
+ QList<int> channelz;
+ QList<int> sizez;
+ QList<QAudioFormat::Endian> byteOrderz;
+ QStringList codecz;
+ QList<QAudioFormat::SampleType> typez;
+};
+
+#endif
diff --git a/src/multimedia/audio/qaudioengine.cpp b/src/multimedia/audio/qaudioengine.cpp
new file mode 100644
index 0000000..930977e
--- /dev/null
+++ b/src/multimedia/audio/qaudioengine.cpp
@@ -0,0 +1,343 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtMultimedia/qaudioengine.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractAudioDeviceInfo
+ \brief The QAbstractAudioDeviceInfo class provides access for QAudioDeviceInfo to access the audio
+ device provided by the plugin.
+ \internal
+
+ \ingroup multimedia
+
+ 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
+*/
+
+/*!
+ \fn virtual QAudioFormat QAbstractAudioDeviceInfo::preferredFormat() const
+ Returns the nearest settings.
+*/
+
+/*!
+ \fn virtual bool QAbstractAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
+ Returns true if \a format is available from audio device.
+*/
+
+/*!
+ \fn virtual QAudioFormat QAbstractAudioDeviceInfo::nearestFormat(const QAudioFormat& format) const
+ Returns the nearest settings \a format.
+*/
+
+/*!
+ \fn virtual QString QAbstractAudioDeviceInfo::deviceName() const
+ Returns the audio device name.
+*/
+
+/*!
+ \fn virtual QStringList QAbstractAudioDeviceInfo::codecList()
+ Returns the list of currently available codecs.
+*/
+
+/*!
+ \fn virtual QList<int> QAbstractAudioDeviceInfo::frequencyList()
+ Returns the list of currently available frequencies.
+*/
+
+/*!
+ \fn virtual QList<int> QAbstractAudioDeviceInfo::channelsList()
+ Returns the list of currently available channels.
+*/
+
+/*!
+ \fn virtual QList<int> QAbstractAudioDeviceInfo::sampleSizeList()
+ Returns the list of currently available sample sizes.
+*/
+
+/*!
+ \fn virtual QList<QAudioFormat::Endian> QAbstractAudioDeviceInfo::byteOrderList()
+ Returns the list of currently available byte orders.
+*/
+
+/*!
+ \fn virtual QList<QAudioFormat::SampleType> QAbstractAudioDeviceInfo::sampleTypeList()
+ Returns the list of currently available sample types.
+*/
+
+/*!
+ \class QAbstractAudioOutput
+ \brief The QAbstractAudioOutput class provides access for QAudioOutput to access the audio
+ device provided by the plugin.
+ \internal
+
+ \ingroup multimedia
+
+ 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 QIODevice* QAbstractAudioOutput::start(QIODevice* device)
+ Uses the \a device as the QIODevice to transfer data. If \a device is null then the class
+ creates an internal QIODevice. Returns a pointer to the QIODevice being used to handle
+ the data transfer. This QIODevice can be used to write() audio data directly. Passing a
+ QIODevice allows the data to be transfered without any extra code.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioOutput::stop()
+ Stops the audio output.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioOutput::reset()
+ Drops all audio data in the buffers, resets buffers to zero.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioOutput::suspend()
+ Stops processing audio data, preserving buffered audio data.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioOutput::resume()
+ Resumes processing audio data after a suspend()
+*/
+
+/*!
+ \fn virtual int QAbstractAudioOutput::bytesFree() const
+ Returns the free space available in bytes in the audio buffer.
+*/
+
+/*!
+ \fn virtual int QAbstractAudioOutput::periodSize() const
+ Returns the period size in bytes.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioOutput::setBufferSize(int value)
+ Sets the audio buffer size to \a value in bytes.
+*/
+
+/*!
+ \fn virtual int QAbstractAudioOutput::bufferSize() const
+ Returns the audio buffer size in bytes.
+*/
+
+/*!
+ \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.
+*/
+
+/*!
+ \fn virtual int QAbstractAudioOutput::notifyInterval() const
+ Returns the notify interval in milliseconds.
+*/
+
+/*!
+ \fn virtual qint64 QAbstractAudioOutput::totalTime() const
+ Returns the amount of audio data processed since start() was called in milliseconds.
+*/
+
+/*!
+ \fn virtual qint64 QAbstractAudioOutput::clock() const
+ Returns the milliseconds since start() was called, including time in Idle and suspend states.
+*/
+
+/*!
+ \fn virtual QAudio::Error QAbstractAudioOutput::error() const
+ Returns the error state.
+*/
+
+/*!
+ \fn virtual QAudio::State QAbstractAudioOutput::state() const
+ Returns the state of audio processing.
+*/
+
+/*!
+ \fn virtual QAudioFormat QAbstractAudioOutput::format() const
+ Returns the QAudioFormat being used.
+*/
+
+/*!
+ \fn QAbstractAudioOutput::stateChanged(QAudio::State state)
+ This signal is emitted when the device \a state has changed.
+*/
+
+/*!
+ \fn QAbstractAudioOutput::notify()
+ This signal is emitted when x ms of audio data has been processed
+ the interval set by setNotifyInterval(x).
+*/
+
+
+/*!
+ \class QAbstractAudioInput
+ \brief The QAbstractAudioInput class provides access for QAudioInput to access the audio
+ device provided by the plugin.
+ \internal
+
+ \ingroup multimedia
+
+ 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 QIODevice* QAbstractAudioInput::start(QIODevice* device)
+ Uses the \a device as the QIODevice to transfer data. If \a device is null
+ then the class creates an internal QIODevice. Returns a pointer to the
+ QIODevice being used to handle the data transfer. This QIODevice can be used to
+ read() audio data directly. Passing a QIODevice allows the data to be transfered
+ without any extra code.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioInput::stop()
+ Stops the audio input.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioInput::reset()
+ Drops all audio data in the buffers, resets buffers to zero.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioInput::suspend()
+ Stops processing audio data, preserving buffered audio data.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioInput::resume()
+ Resumes processing audio data after a suspend().
+*/
+
+/*!
+ \fn virtual int QAbstractAudioInput::bytesReady() const
+ Returns the amount of audio data available to read in bytes.
+*/
+
+/*!
+ \fn virtual int QAbstractAudioInput::periodSize() const
+ Returns the period size in bytes.
+*/
+
+/*!
+ \fn virtual void QAbstractAudioInput::setBufferSize(int value)
+ Sets the audio buffer size to \a value in milliseconds.
+*/
+
+/*!
+ \fn virtual int QAbstractAudioInput::bufferSize() const
+ Returns the audio buffer size in milliseconds.
+*/
+
+/*!
+ \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.
+*/
+
+/*!
+ \fn virtual int QAbstractAudioInput::notifyInterval() const
+ Returns the notify interval in milliseconds.
+*/
+
+/*!
+ \fn virtual qint64 QAbstractAudioInput::totalTime() const
+ Returns the amount of audio data processed since start() was called in milliseconds.
+*/
+
+/*!
+ \fn virtual qint64 QAbstractAudioInput::clock() const
+ Returns the milliseconds since start() was called, including time in Idle and suspend states.
+*/
+
+/*!
+ \fn virtual QAudio::Error QAbstractAudioInput::error() const
+ Returns the error state.
+*/
+
+/*!
+ \fn virtual QAudio::State QAbstractAudioInput::state() const
+ Returns the state of audio processing.
+*/
+
+/*!
+ \fn virtual QAudioFormat QAbstractAudioInput::format() const
+ Returns the QAudioFormat being used
+*/
+
+/*!
+ \fn QAbstractAudioInput::stateChanged(QAudio::State state)
+ This signal is emitted when the device \a state has changed.
+*/
+
+/*!
+ \fn QAbstractAudioInput::notify()
+ This signal is emitted when x ms of audio data has been processed
+ the interval set by setNotifyInterval(x).
+*/
+
+
+QT_END_NAMESPACE
diff --git a/src/multimedia/audio/qaudioengine.h b/src/multimedia/audio/qaudioengine.h
new file mode 100644
index 0000000..b0aa762
--- /dev/null
+++ b/src/multimedia/audio/qaudioengine.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAUDIOENGINE_H
+#define QAUDIOENGINE_H
+
+#include <QtCore/qglobal.h>
+#include <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/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 QAudioFormat nearestFormat(const QAudioFormat &format) const = 0;
+ virtual QString deviceName() const = 0;
+ virtual QStringList codecList() = 0;
+ virtual QList<int> frequencyList() = 0;
+ virtual QList<int> channelsList() = 0;
+ virtual QList<int> sampleSizeList() = 0;
+ virtual QList<QAudioFormat::Endian> byteOrderList() = 0;
+ virtual QList<QAudioFormat::SampleType> sampleTypeList() = 0;
+};
+
+class Q_MULTIMEDIA_EXPORT QAbstractAudioOutput : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual QIODevice* start(QIODevice* device) = 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 totalTime() const = 0;
+ virtual qint64 clock() const = 0;
+ virtual QAudio::Error error() const = 0;
+ virtual QAudio::State state() const = 0;
+ virtual QAudioFormat format() const = 0;
+
+Q_SIGNALS:
+ void stateChanged(QAudio::State);
+ void notify();
+};
+
+class Q_MULTIMEDIA_EXPORT QAbstractAudioInput : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual QIODevice* start(QIODevice* device) = 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 totalTime() const = 0;
+ virtual qint64 clock() const = 0;
+ virtual QAudio::Error error() const = 0;
+ virtual QAudio::State state() const = 0;
+ virtual QAudioFormat format() const = 0;
+
+Q_SIGNALS:
+ void stateChanged(QAudio::State);
+ void notify();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAUDIOENGINE_H
diff --git a/src/multimedia/audio/qaudioengineplugin.cpp b/src/multimedia/audio/qaudioengineplugin.cpp
new file mode 100644
index 0000000..6e39004
--- /dev/null
+++ b/src/multimedia/audio/qaudioengineplugin.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtMultimedia/qaudioengineplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+QAudioEnginePlugin::QAudioEnginePlugin(QObject* parent) :
+ QObject(parent)
+{}
+
+QAudioEnginePlugin::~QAudioEnginePlugin()
+{}
+
+QT_END_NAMESPACE
diff --git a/src/multimedia/audio/qaudioengineplugin.h b/src/multimedia/audio/qaudioengineplugin.h
new file mode 100644
index 0000000..8eab2d7
--- /dev/null
+++ b/src/multimedia/audio/qaudioengineplugin.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QAUDIOENGINEPLUGIN_H
+#define QAUDIOENGINEPLUGIN_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Multimedia)
+
+struct Q_MULTIMEDIA_EXPORT QAudioEngineFactoryInterface : public QFactoryInterface
+{
+ virtual QList<QByteArray> deviceList(QAudio::Mode) const = 0;
+ virtual QAbstractAudioInput* createInput(const QByteArray& device, const QAudioFormat& format = QAudioFormat()) = 0;
+ virtual QAbstractAudioOutput* createOutput(const QByteArray& device, const QAudioFormat& format = QAudioFormat()) = 0;
+ virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0;
+};
+
+#define QAudioEngineFactoryInterface_iid \
+ "com.nokia.qt.QAudioEngineFactoryInterface"
+Q_DECLARE_INTERFACE(QAudioEngineFactoryInterface, QAudioEngineFactoryInterface_iid)
+
+class Q_MULTIMEDIA_EXPORT QAudioEnginePlugin : public QObject, public QAudioEngineFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QAudioEngineFactoryInterface:QFactoryInterface)
+
+public:
+ QAudioEnginePlugin(QObject *parent = 0);
+ ~QAudioEnginePlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QList<QByteArray> deviceList(QAudio::Mode) const = 0;
+ virtual QAbstractAudioInput* createInput(const QByteArray& device, const QAudioFormat& format = QAudioFormat()) = 0;
+ virtual QAbstractAudioOutput* createOutput(const QByteArray& device, const QAudioFormat& format = QAudioFormat()) = 0;
+ virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAUDIOENGINEPLUGIN_H
diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp
new file mode 100644
index 0000000..6632c63
--- /dev/null
+++ b/src/multimedia/audio/qaudioformat.cpp
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtMultimedia/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;
+ }
+
+ QString codec;
+ QAudioFormat::Endian byteOrder;
+ QAudioFormat::SampleType sampleType;
+
+ int frequency;
+ int channels;
+ int sampleSize;
+};
+
+/*!
+ \class QAudioFormat
+ \brief The QAudioFormat class stores audio parameter information.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia
+ \since 4.6
+
+ 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 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 Frequency
+ \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)
+ \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
+
+ 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 QAudioDeviceInfo class
+ description for details.
+*/
+
+/*!
+ Construct a new audio format.
+
+ Values are initialized as follows:
+ \list
+ \o frequency() = -1
+ \o channels() = -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.
+*/
+
+QAudioFormat::QAudioFormat(const QAudioFormat &other):
+ d(other.d)
+{
+}
+
+/*!
+ Destroy this audio format.
+*/
+
+QAudioFormat::~QAudioFormat()
+{
+}
+
+/*!
+ Assigns \a other to this QAudioFormat implementation.
+*/
+
+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.
+*/
+
+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.
+*/
+
+bool QAudioFormat::operator!=(const QAudioFormat& other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Returns true if any of the parameters are invalid.
+*/
+
+bool QAudioFormat::isNull() const
+{
+ return d->frequency == -1 && d->channels == -1 &&
+ d->sampleSize == -1 &&
+ d->byteOrder == QAudioFormat::Endian(QSysInfo::ByteOrder) &&
+ d->sampleType == QAudioFormat::Unknown &&
+ d->codec.isNull();
+}
+
+/*!
+ Sets the frequency to \a frequency.
+*/
+
+void QAudioFormat::setFrequency(int frequency)
+{
+ d->frequency = frequency;
+}
+
+/*!
+ Returns the current frequency value.
+*/
+
+int QAudioFormat::frequency() const
+{
+ return d->frequency;
+}
+
+/*!
+ Sets the channels to \a channels.
+*/
+
+void QAudioFormat::setChannels(int channels)
+{
+ d->channels = channels;
+}
+
+/*!
+ Returns the current channel value.
+*/
+
+int QAudioFormat::channels() const
+{
+ return d->channels;
+}
+
+/*!
+ Sets the sampleSize to \a sampleSize.
+*/
+
+void QAudioFormat::setSampleSize(int sampleSize)
+{
+ d->sampleSize = sampleSize;
+}
+
+/*!
+ Returns the current sampleSize value.
+*/
+
+int QAudioFormat::sampleSize() const
+{
+ return d->sampleSize;
+}
+
+/*!
+ Sets the codec to \a codec.
+
+ \sa QAudioDeviceInfo::supportedCodecs()
+*/
+
+void QAudioFormat::setCodec(QString codec)
+{
+ d->codec = codec;
+}
+
+/*!
+ Returns the current codec value.
+
+ \sa QAudioDeviceInfo::supportedCodecs()
+*/
+
+QString QAudioFormat::codec() const
+{
+ return d->codec;
+}
+
+/*!
+ Sets the byteOrder to \a byteOrder.
+*/
+
+void QAudioFormat::setByteOrder(QAudioFormat::Endian byteOrder)
+{
+ d->byteOrder = byteOrder;
+}
+
+/*!
+ Returns the current byteOrder value.
+*/
+
+QAudioFormat::Endian QAudioFormat::byteOrder() const
+{
+ return d->byteOrder;
+}
+
+/*!
+ Sets the sampleType to \a sampleType.
+*/
+
+void QAudioFormat::setSampleType(QAudioFormat::SampleType sampleType)
+{
+ d->sampleType = sampleType;
+}
+
+/*!
+ Returns the current SampleType value.
+*/
+
+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
+
diff --git a/src/multimedia/audio/qaudioformat.h b/src/multimedia/audio/qaudioformat.h
new file mode 100644
index 0000000..c740969
--- /dev/null
+++ b/src/multimedia/audio/qaudioformat.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QAUDIOFORMAT_H
+#define QAUDIOFORMAT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.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 isNull() const;
+
+ void setFrequency(int frequency);
+ int frequency() const;
+
+ void setChannels(int channels);
+ int channels() const;
+
+ void setSampleSize(int sampleSize);
+ int sampleSize() const;
+
+ void setCodec(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
diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp
new file mode 100644
index 0000000..17cacc6
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput.cpp
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+#include <QtMultimedia/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 4.6
+
+ 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 QAudioDeviceId. 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 QAudioDeviceId 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:
+
+ \code
+ {
+ QFile outputFile;
+ outputFile.setFileName("/tmp/test.raw");
+ outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
+
+ QAudioFormat format;
+ // set up the format you want, eg.
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+
+ QAudioInput *audio = new QAudioInput(format, this);
+ QTimer::singleShot(3000, this, SLOT(stopRecording()));
+ audio->start(outputFile);
+ // Records audio for 3000ms
+ }
+ \endcode
+
+ 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.
+
+ \code
+ void stopRecording()
+ {
+ audio->stop();
+ outputFile->close();
+ }
+ \endcode
+
+ 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 totalTime()
+ 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 clock() 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.
+
+ \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.
+*/
+
+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 \a id of the audio input device is used with the input
+ \a format parameters.
+*/
+
+QAudioInput::QAudioInput(const QAudioDeviceId &id, const QAudioFormat &format, QObject *parent):
+ QObject(parent)
+{
+ d = QAudioDeviceFactory::createInputDevice(id, 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.
+ If \a device is null then the class creates an internal QIODevice.
+ Returns a pointer to the QIODevice being used to handle the data
+ transfer. This QIODevice can be used to read() audio data
+ directly.
+ Passing a QIODevice allows the data to be transfered without any extra code.
+ All that is required is to open the QIODevice.
+
+ /sa QIODevice
+*/
+
+QIODevice* QAudioInput::start(QIODevice* device)
+{
+ /*
+ PULL MODE (valid QIODevice)
+ -If currently not StopState, stop
+ -If previous start was push mode, delete internal QIODevice.
+ -open audio input.
+ If ok, NoError and ActiveState, else OpenError and StopState.
+ -emit stateChanged()
+ -return device
+
+ PUSH MODE (device = 0)
+ -If currently not StopState, stop
+ -If no internal QIODevice, create one.
+ -open audio input.
+ -If ok, NoError and IdleState, else OpenError and StopState
+ -emit stateChanged()
+ -return internal QIODevice
+ */
+ return d->start(device);
+}
+
+/*!
+ Returns the QAudioFormat being used.
+*/
+
+QAudioFormat QAudioInput::format() const
+{
+ return d->format();
+}
+
+/*!
+ Stops the audio input.
+*/
+
+void QAudioInput::stop()
+{
+ /*
+ -If StopState, return
+ -set to StopState
+ -detach from audio device
+ -emit stateChanged()
+ */
+ d->stop();
+}
+
+/*!
+ Drops all audio data in the buffers, resets buffers to zero.
+*/
+
+void QAudioInput::reset()
+{
+ /*
+ -drop all buffered audio, set buffers to zero.
+ -call stop()
+ */
+ d->reset();
+}
+
+/*!
+ Stops processing audio data, preserving buffered audio data.
+*/
+
+void QAudioInput::suspend()
+{
+ /*
+ -If not ActiveState|IdleState, return
+ -stop processing audio, saving all buffered audio data
+ -set NoError and SuspendState
+ -emit stateChanged()
+ */
+ d->suspend();
+}
+
+/*!
+ Resumes processing audio data after a suspend().
+*/
+
+void QAudioInput::resume()
+{
+ /*
+ -If SuspendState, return
+ -resume audio
+ -(PULL MODE): set ActiveState, NoError
+ -(PUSH MODE): set IdleState, NoError
+ -kick start audio if needed
+ -emit stateChanged()
+ */
+ 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.
+
+*/
+
+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().
+
+*/
+
+int QAudioInput::bufferSize() const
+{
+ return d->bufferSize();
+}
+
+/*!
+ Returns the amount of audio data available to read in bytes.
+*/
+
+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.
+*/
+
+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 resolution of the timer is platform specific.
+*/
+
+void QAudioInput::setNotifyInterval(int ms)
+{
+ d->setNotifyInterval(ms);
+}
+
+/*!
+ Returns the notify interval in milliseconds.
+*/
+
+int QAudioInput::notifyInterval() const
+{
+ return d->notifyInterval();
+}
+
+/*!
+ Returns the amount of audio data processed since start()
+ was called in microseconds.
+*/
+
+qint64 QAudioInput::totalTime() const
+{
+ return d->totalTime();
+}
+
+/*!
+ Returns the microseconds since start() was called, including time in Idle and
+ Suspend states.
+*/
+
+qint64 QAudioInput::clock() const
+{
+ return d->clock();
+}
+
+/*!
+ Returns the error state.
+*/
+
+QAudio::Error QAudioInput::error() const
+{
+ return d->error();
+}
+
+/*!
+ Returns the state of audio processing.
+*/
+
+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.
+*/
+
+/*!
+ \fn QAudioInput::notify()
+ This signal is emitted when x ms of audio data has been processed
+ the interval set by setNotifyInterval(x).
+*/
+
+QT_END_NAMESPACE
+
diff --git a/src/multimedia/audio/qaudioinput.h b/src/multimedia/audio/qaudioinput.h
new file mode 100644
index 0000000..b0f1aed
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QAUDIOINPUT_H
+#define QAUDIOINPUT_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qglobal.h>
+
+#include <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qaudiodeviceid.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 QAudioDeviceId &id, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
+ ~QAudioInput();
+
+ QAudioFormat format() const;
+
+ QIODevice* start(QIODevice *device = 0);
+ 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 totalTime() const;
+ qint64 clock() 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
diff --git a/src/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/audio/qaudioinput_alsa_p.cpp
new file mode 100644
index 0000000..6f00469
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp
@@ -0,0 +1,688 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#include <QtCore/qcoreapplication.h>
+#include "qaudioinput_alsa_p.h"
+
+//#define DEBUG_AUDIO 1
+
+QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
+ settings(audioFormat)
+{
+ 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;
+ audioBuffer = 0;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::StopState;
+ audioSource = 0;
+ pullMode = true;
+ resuming = false;
+
+ QStringList list1 = QString(tr(device)).split(tr(":"));
+ m_device = QByteArray(list1.at(0).toLocal8Bit().constData());
+
+ 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;
+}
+
+
+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 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_S16;
+
+ 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 snd_pcm_hw_params_set_format( handle, hwparams, format);
+}
+
+QIODevice* QAudioInputPrivate::start(QIODevice* device)
+{
+ if(deviceState != QAudio::StopState)
+ close();
+
+ if(!pullMode && audioSource) {
+ delete audioSource;
+ }
+
+ if(device) {
+ //set to pull mode
+ pullMode = true;
+ audioSource = device;
+ } else {
+ //set to push mode
+ pullMode = false;
+ audioSource = new InputPrivate(this);
+ audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+ }
+
+ if( !open() )
+ return 0;
+
+ emit stateChanged(deviceState);
+
+ return audioSource;
+}
+
+void QAudioInputPrivate::stop()
+{
+ if(deviceState == QAudio::StopState)
+ return;
+
+ deviceState = QAudio::StopState;
+
+ close();
+ emit stateChanged(deviceState);
+}
+
+bool QAudioInputPrivate::open()
+{
+#ifdef DEBUG_AUDIO
+ QTime now(QTime::currentTime());
+ qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
+#endif
+ timeStamp.restart();
+
+ int dir;
+ int err=-1;
+ int count=0;
+ unsigned int freakuency=settings.frequency();
+
+ QString dev = QString(tr(m_device.constData()));
+ if(!dev.contains(tr("default"))) {
+ dev = QString(tr("default:CARD=%1")).arg(tr(m_device.constData()));
+ }
+
+ // 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::StopState;
+ 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(tr("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(tr("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(tr("QAudioInput: snd_pcm_hw_params_set_access: err = %1")).arg(err);
+ }
+ }
+ if ( !fatal ) {
+ err = setFormat();
+ if ( err < 0 ) {
+ fatal = true;
+ errMessage = QString(tr("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(tr("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(tr("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(tr("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(tr("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(tr("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(tr("QAudioInput: snd_pcm_hw_params: err = %1")).arg(err);
+ }
+ }
+ if( err < 0) {
+ qWarning()<<errMessage;
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ 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
+ if(audioBuffer == 0)
+ audioBuffer = new char[buffer_size];
+ snd_pcm_prepare( handle );
+ snd_pcm_start(handle);
+
+ // Step 5: Setup timer
+ bytesAvailable = bytesReady();
+
+ 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;
+ deviceState = QAudio::ActiveState;
+
+ totalTimeValue = 0;
+
+ return true;
+}
+
+void QAudioInputPrivate::close()
+{
+ deviceState = QAudio::StopState;
+ timer->stop();
+
+ if ( handle ) {
+ snd_pcm_drop( handle );
+ snd_pcm_close( handle );
+ handle = 0;
+ delete [] audioBuffer;
+ audioBuffer=0;
+ }
+}
+
+int QAudioInputPrivate::bytesReady() const
+{
+ if(resuming)
+ return period_size;
+
+ if(deviceState != QAudio::ActiveState)
+ return 0;
+ int frames = snd_pcm_avail_update(handle);
+ if((int)frames > (int)buffer_frames)
+ frames = buffer_frames;
+
+ return snd_pcm_frames_to_bytes(handle, frames);
+}
+
+qint64 QAudioInputPrivate::read(char* data, qint64 len)
+{
+ Q_UNUSED(data)
+ Q_UNUSED(len)
+ // Read in some audio data and write it to QIODevice, pull mode
+ if ( !handle )
+ return 0;
+
+ bytesAvailable = bytesReady();
+
+ int count=0, err = 0;
+ while(count < 5) {
+ int chunks = bytesAvailable/period_size;
+ int frames = chunks*period_frames;
+ if(frames > (int)buffer_frames)
+ frames = buffer_frames;
+ int readFrames = snd_pcm_readi(handle, audioBuffer, frames);
+ if (readFrames >= 0) {
+ err = snd_pcm_frames_to_bytes(handle, readFrames);
+#ifdef DEBUG_AUDIO
+ qDebug()<<QString(tr("PULL: read in bytes = %1 (frames=%2)")).arg(err).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++;
+ }
+ if(err > 0) {
+ // got some send it onward
+#ifdef DEBUG_AUDIO
+ qDebug()<<"PULL: frames to write to QIODevice = "<<
+ snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes";
+#endif
+ if(deviceState != QAudio::ActiveState)
+ return 0;
+
+ qint64 l = audioSource->write(audioBuffer,err);
+ if(l < 0) {
+ close();
+ errorState = QAudio::IOError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ } else if(l == 0) {
+ errorState = QAudio::NoError;
+ deviceState = QAudio::IdleState;
+ } else {
+ totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency();
+ resuming = false;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ }
+ return l;
+ }
+ return 0;
+}
+
+void QAudioInputPrivate::resume()
+{
+ if(deviceState == QAudio::SuspendState) {
+ 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(buffer_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 = ms;
+}
+
+int QAudioInputPrivate::notifyInterval() const
+{
+ return intervalTime;
+}
+
+qint64 QAudioInputPrivate::totalTime() const
+{
+ return totalTimeValue;
+}
+
+void QAudioInputPrivate::suspend()
+{
+ if(deviceState == QAudio::ActiveState||resuming) {
+ timer->stop();
+ deviceState = QAudio::SuspendState;
+ emit stateChanged(deviceState);
+ }
+}
+
+void QAudioInputPrivate::userFeed()
+{
+ if(deviceState == QAudio::StopState || deviceState == QAudio::SuspendState)
+ 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,0);
+ } else {
+ // emits readyRead() so user will call read() on QIODevice to get some audio data
+ InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
+ a->trigger();
+ }
+ bytesAvailable = bytesReady();
+
+ if(deviceState != QAudio::ActiveState)
+ return true;
+
+ if(timeStamp.elapsed() > intervalTime && intervalTime > 50) {
+ emit notify();
+ timeStamp.restart();
+ }
+ return true;
+}
+
+qint64 QAudioInputPrivate::clock() const
+{
+ if(!handle)
+ return 0;
+
+ if(deviceState != QAudio::ActiveState)
+ return 0;
+
+ snd_pcm_status_t* status;
+ snd_pcm_status_alloca(&status);
+
+ snd_timestamp_t t1,t2;
+ if( snd_pcm_status(handle, status) >= 0) {
+ snd_pcm_status_get_tstamp(status,&t1);
+ snd_pcm_status_get_trigger_tstamp(status,&t2);
+ t1.tv_sec-=t2.tv_sec;
+
+ signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec;
+ if(l < 0) {
+ t1.tv_sec--;
+ l = -l;
+ l %= 1000000;
+ }
+ return ((t1.tv_sec * 1000)+l/1000);
+ } else
+ return 0;
+}
+
+void QAudioInputPrivate::reset()
+{
+ if(handle)
+ snd_pcm_reset(handle);
+}
+
+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)
+{
+ // push mode, user read() called
+ if((audioDevice->state() != QAudio::ActiveState) && !audioDevice->resuming)
+ return 0;
+
+ int readFrames;
+ int count=0, err = 0;
+
+ while(count < 5) {
+ int frames = snd_pcm_bytes_to_frames(audioDevice->handle, len);
+ readFrames = snd_pcm_readi(audioDevice->handle, data, frames);
+ if (readFrames >= 0) {
+ err = snd_pcm_frames_to_bytes(audioDevice->handle, readFrames);
+#ifdef DEBUG_AUDIO
+ qDebug()<<QString(tr("PUSH: read in bytes = %1 (frames=%2)")).arg(err).arg(readFrames).toLatin1().constData();
+#endif
+ break;
+ } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
+ audioDevice->errorState = QAudio::IOError;
+ err = 0;
+ break;
+ } else {
+ if(readFrames == -EPIPE) {
+ audioDevice->errorState = QAudio::UnderrunError;
+ err = snd_pcm_prepare(audioDevice->handle);
+ } else if(readFrames == -ESTRPIPE) {
+ err = snd_pcm_prepare(audioDevice->handle);
+ }
+ if(err != 0) break;
+ }
+ count++;
+ }
+ if(err > 0 && readFrames > 0) {
+ audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.frequency()*1000;
+ audioDevice->deviceState = QAudio::ActiveState;
+ return err;
+ }
+ return 0;
+}
+
+qint64 InputPrivate::writeData(const char* data, qint64 len)
+{
+ Q_UNUSED(data)
+ Q_UNUSED(len)
+ return 0;
+}
+
+void InputPrivate::trigger()
+{
+ emit readyRead();
+}
+
diff --git a/src/multimedia/audio/qaudioinput_alsa_p.h b/src/multimedia/audio/qaudioinput_alsa_p.h
new file mode 100644
index 0000000..21c8064
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput_alsa_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+class InputPrivate;
+
+class QAudioInputPrivate : public QAbstractAudioInput
+{
+ Q_OBJECT
+public:
+ QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat);
+ ~QAudioInputPrivate();
+
+ qint64 read(char* data, qint64 len);
+
+ QIODevice* start(QIODevice* device = 0);
+ 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 totalTime() const;
+ qint64 clock() const;
+ QAudio::Error error() const;
+ QAudio::State state() const;
+ 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 xrun_recovery(int err);
+ int setFormat();
+ bool open();
+ void close();
+ void drain();
+
+ QTimer* timer;
+ QTime timeStamp;
+ int intervalTime;
+ char* audioBuffer;
+ 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;
+};
+
+#endif
diff --git a/src/multimedia/audio/qaudioinput_mac_p.cpp b/src/multimedia/audio/qaudioinput_mac_p.cpp
new file mode 100644
index 0000000..5400c85
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput_mac_p.cpp
@@ -0,0 +1,930 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#include <QtCore/qendian.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdebug.h>
+
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioinput.h>
+
+#include "qaudio_mac_p.h"
+#include "qaudioinput_mac_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+
+namespace
+{
+
+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;
+ }
+
+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;
+ }
+
+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_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 (inputFormat.mSampleRate != outputFormat.mSampleRate) {
+ 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 wasEmpty = m_buffer->used() == 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);
+
+ bool wecan = true;
+ int copied = 0;
+
+ const int available = m_buffer->free();
+
+ while (err == noErr && wecan) {
+ QAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(available);
+
+ if (region.second > 0) {
+ 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);
+ }
+ else
+ wecan = false;
+ }
+
+ 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 (wasEmpty && 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)
+ {
+ 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, QAudioFormat const& format):
+ audioFormat(format)
+{
+ QDataStream ds(device);
+ quint32 did, mode;
+
+ ds >> did >> mode;
+
+ if (QAudio::Mode(mode) == QAudio::AudioOutput)
+ errorCode = QAudio::OpenError;
+ else {
+ isOpen = false;
+ audioDeviceId = AudioDeviceID(did);
+ audioUnit = 0;
+ startTime = 0;
+ totalFrames = 0;
+ audioBuffer = 0;
+ internalBufferSize = default_buffer_size;
+ clockFrequency = AudioGetHostClockFrequency() / 1000;
+ errorCode = QAudio::NoError;
+ stateCode = QAudio::StopState;
+
+ intervalTimer = new QTimer(this);
+ intervalTimer->setInterval(1000);
+ connect(intervalTimer, SIGNAL(timeout()), SIGNAL(notify()));
+ }
+}
+
+QAudioInputPrivate::~QAudioInputPrivate()
+{
+ close();
+}
+
+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: Unabled 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: Unabled 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
+ streamFormat = toAudioStreamBasicDescription(audioFormat);
+
+ size = sizeof(deviceFormat);
+ if (AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input,
+ 1,
+ &deviceFormat,
+ &size) != noErr) {
+ qWarning() << "QAudioInput: Unable to retrieve device format";
+ return false;
+ }
+
+ // If the device frequency is different to the requested use a converter
+ if (deviceFormat.mSampleRate != streamFormat.mSampleRate) {
+ AudioUnitSetProperty(audioUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ 1,
+ &deviceFormat,
+ sizeof(streamFormat));
+ }
+ else {
+ AudioUnitSetProperty(audioUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ 1,
+ &streamFormat,
+ sizeof(streamFormat));
+ }
+
+ // 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.mSampleRate / deviceFormat.mSampleRate) *
+ streamFormat.mBytesPerFrame;
+ if (internalBufferSize < periodSizeBytes * 2)
+ internalBufferSize = periodSizeBytes * 2;
+ else
+ internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
+
+ audioBuffer = new QAudioInputBuffer(internalBufferSize,
+ periodSizeBytes,
+ deviceFormat,
+ streamFormat,
+ this);
+
+ audioIO = new 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;
+}
+
+QIODevice* QAudioInputPrivate::start(QIODevice* device)
+{
+ QIODevice* op = device;
+
+ if (!open()) {
+ stateCode = QAudio::StopState;
+ errorCode = QAudio::OpenError;
+ return audioIO;
+ }
+
+ reset();
+ audioBuffer->reset();
+ audioBuffer->setFlushDevice(op);
+
+ if (op == 0)
+ op = audioIO;
+
+ // Start
+ startTime = AudioGetCurrentHostTime();
+ totalFrames = 0;
+
+ audioThreadStart();
+
+ return op;
+}
+
+void QAudioInputPrivate::stop()
+{
+ QMutexLocker lock(&mutex);
+ if (stateCode != QAudio::StopState) {
+ audioThreadStop();
+ audioBuffer->flush(true);
+
+ errorCode = QAudio::NoError;
+ stateCode = QAudio::StopState;
+ QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
+ }
+}
+
+void QAudioInputPrivate::reset()
+{
+ QMutexLocker lock(&mutex);
+ if (stateCode != QAudio::StopState) {
+ audioThreadStop();
+
+ errorCode = QAudio::NoError;
+ stateCode = QAudio::StopState;
+ 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::SuspendState;
+ QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
+ }
+}
+
+void QAudioInputPrivate::resume()
+{
+ QMutexLocker lock(&mutex);
+ if (stateCode == QAudio::SuspendState) {
+ 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)
+{
+ intervalTimer->setInterval(milliSeconds);
+}
+
+int QAudioInputPrivate::notifyInterval() const
+{
+ return intervalTimer->interval();
+}
+
+qint64 QAudioInputPrivate::totalTime() const
+{
+ return totalFrames * 1000000 / audioFormat.frequency();
+}
+
+qint64 QAudioInputPrivate::clock() const
+{
+ 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::StopState;
+ QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
+ }
+}
+
+void QAudioInputPrivate::startTimers()
+{
+ audioBuffer->startFlushTimer();
+ 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"
+
diff --git a/src/multimedia/audio/qaudioinput_mac_p.h b/src/multimedia/audio/qaudioinput_mac_p.h
new file mode 100644
index 0000000..98ef9ce
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput_mac_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qaudioengine.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QTimer;
+class QIODevice;
+
+namespace
+{
+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;
+ QAudioInputBuffer* audioBuffer;
+ QMutex mutex;
+ QWaitCondition threadFinished;
+ QAtomicInt audioThreadState;
+ QTimer* intervalTimer;
+ AudioStreamBasicDescription streamFormat;
+ AudioStreamBasicDescription deviceFormat;
+
+ QAudioInputPrivate(const QByteArray& device, QAudioFormat const& format);
+ ~QAudioInputPrivate();
+
+ bool open();
+ void close();
+
+ QAudioFormat format() const;
+
+ QIODevice* 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 totalTime() const;
+ qint64 clock() const;
+
+ QAudio::Error error() const;
+ QAudio::State state() const;
+
+ void audioThreadStart();
+ void audioThreadStop();
+
+ void audioDeviceStop();
+ void audioDeviceFull();
+ void audioDeviceError();
+
+ void startTimers();
+ void stopTimers();
+
+signals:
+ void stateChanged(QAudio::State);
+ void notify();
+
+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
diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp
new file mode 100644
index 0000000..e5b6e0d
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput_win32_p.cpp
@@ -0,0 +1,540 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+
+#include "qaudioinput_win32_p.h"
+
+//#define DEBUG_AUDIO 1
+
+
+QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
+ settings(audioFormat)
+{
+ bytesAvailable = 0;
+ buffer_size = 0;
+ period_size = 0;
+ m_device = device;
+ totalTimeValue = 0;
+ intervalTime = 1000;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::StopState;
+ audioSource = 0;
+ pullMode = true;
+ resuming = false;
+
+ connect(this,SIGNAL(processMore()),SLOT(deviceReady()));
+
+ InitializeCriticalSection(&waveInCriticalSection);
+}
+
+QAudioInputPrivate::~QAudioInputPrivate()
+{
+ close();
+ DeleteCriticalSection(&waveInCriticalSection);
+}
+
+void 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;
+
+ switch(uMsg) {
+ case WIM_OPEN:
+ break;
+ case WIM_DATA:
+ EnterCriticalSection(&waveInCriticalSection);
+ if(qAudio->waveFreeBlockCount > 0)
+ qAudio->waveFreeBlockCount--;
+ LeaveCriticalSection(&waveInCriticalSection);
+ qAudio->feedback();
+ break;
+ case WIM_CLOSE:
+ 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)
+{
+ HeapFree(GetProcessHeap(), 0, blockArray);
+}
+
+QAudio::Error QAudioInputPrivate::error() const
+{
+ return errorState;
+}
+
+QAudio::State QAudioInputPrivate::state() const
+{
+ return deviceState;
+}
+
+QAudioFormat QAudioInputPrivate::format() const
+{
+ return settings;
+}
+
+QIODevice* QAudioInputPrivate::start(QIODevice* device)
+{
+ if(deviceState != QAudio::StopState)
+ close();
+
+ if(!pullMode && audioSource) {
+ delete audioSource;
+ }
+
+ if(device) {
+ //set to pull mode
+ pullMode = true;
+ audioSource = device;
+ } else {
+ //set to push mode
+ pullMode = false;
+ audioSource = new InputPrivate(this);
+ audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+ }
+
+ if( !open() )
+ return 0;
+
+ emit stateChanged(deviceState);
+
+ return audioSource;
+}
+
+void QAudioInputPrivate::stop()
+{
+ if(deviceState == QAudio::StopState)
+ return;
+
+ deviceState = QAudio::StopState;
+
+ 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;
+ if(buffer_size == 0) {
+ // Default buffer size, 100ms, default period size is 20ms
+ buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.1;
+ period_size = buffer_size/5;
+ } else {
+ period_size = buffer_size/5;
+ }
+ timeStamp.restart();
+ 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;
+
+ UINT_PTR devId = WAVE_MAPPER;
+
+ WAVEINCAPS wic;
+ unsigned long iNumDevs,ii;
+ iNumDevs = waveInGetNumDevs();
+ for(ii=0;ii<iNumDevs;ii++) {
+ if(waveInGetDevCaps(ii, &wic, sizeof(WAVEINCAPS))
+ == MMSYSERR_NOERROR) {
+ QString tmp;
+ tmp = QString::fromUtf16((const unsigned short*)wic.szPname);
+ if(tmp.compare(tr(m_device)) == 0) {
+ devId = ii;
+ break;
+ }
+ }
+ }
+
+ if(waveInOpen(&hWaveIn, devId, &wfx,
+ (DWORD_PTR)&waveInProc,
+ (DWORD_PTR) this,
+ CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ qWarning("QAudioInput: failed to open audio device");
+ return false;
+ }
+ waveBlocks = allocateBlocks(period_size, buffer_size/period_size);
+ waveFreeBlockCount = buffer_size/period_size;
+ waveCurrentBlock = 0;
+
+ 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::StopState;
+ emit stateChanged(deviceState);
+ return false;
+ }
+ }
+ result = waveInStart(hWaveIn);
+ if(result) {
+ qWarning("QAudioInput: failed to start audio input");
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ return false;
+ }
+ timeStampOpened.restart();
+ totalTimeValue = 0;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ return true;
+}
+
+void QAudioInputPrivate::close()
+{
+ deviceState = QAudio::StopState;
+ int delay = (buffer_size-bytesReady())*1000/(settings.frequency()
+ *settings.channels()*(settings.sampleSize()/8));
+ waveInReset(hWaveIn);
+ Sleep(delay+10);
+
+ for(int i=0; i<waveFreeBlockCount; i++) {
+ if(waveBlocks[i].dwFlags & WHDR_PREPARED)
+ waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR));
+ }
+ freeBlocks(waveBlocks);
+ waveInClose(hWaveIn);
+}
+
+int QAudioInputPrivate::bytesReady() const
+{
+ 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) {
+ if(pullMode) {
+ l = audioSource->write(waveBlocks[header].lpData,
+ waveBlocks[header].dwBytesRecorded);
+#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 += waveBlocks[header].dwBytesRecorded
+ /((settings.channels()*settings.sampleSize()/8))
+ *10000/settings.frequency()*100;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ resuming = false;
+ }
+ } else {
+ // push mode
+ memcpy(p,waveBlocks[header].lpData,waveBlocks[header].dwBytesRecorded);
+ l = waveBlocks[header].dwBytesRecorded;
+#ifdef DEBUG_AUDIO
+ qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
+#endif
+ totalTimeValue += waveBlocks[header].dwBytesRecorded
+ /((settings.channels()*settings.sampleSize()/8))
+ *10000/settings.frequency()*100;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ resuming = false;
+ }
+ } else {
+ //no data, not ready yet, next time
+ return 0;
+ }
+ EnterCriticalSection(&waveInCriticalSection);
+ waveFreeBlockCount++;
+ LeaveCriticalSection(&waveInCriticalSection);
+ waveBlocks[header].dwBytesRecorded=0;
+ waveBlocks[header].dwFlags = 0L;
+ result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
+ if(result != MMSYSERR_NOERROR) {
+ qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result);
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ }
+ result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR));
+ if(result != MMSYSERR_NOERROR) {
+ qWarning("QAudioInput: failed to setup block %d,err=%d",header,result);
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ }
+ header++;
+ if(header >= buffer_size/period_size)
+ header = 0;
+ p+=l;
+
+ if(!pullMode) {
+ if(l+period_size > len && waveFreeBlockCount == buffer_size/period_size)
+ done = true;
+ } else {
+ if(waveFreeBlockCount == buffer_size/period_size)
+ done = true;
+ }
+ written+=l;
+ }
+#ifdef DEBUG_AUDIO
+ qDebug()<<"read in len="<<written;
+#endif
+ return written;
+}
+
+void QAudioInputPrivate::resume()
+{
+ if(deviceState == QAudio::SuspendState) {
+ 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::StopState;
+ emit stateChanged(deviceState);
+ return;
+ }
+ }
+ waveFreeBlockCount = buffer_size/period_size;
+ waveCurrentBlock = 0;
+ header = 0;
+ resuming = true;
+ 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 = ms;
+}
+
+int QAudioInputPrivate::notifyInterval() const
+{
+ return intervalTime;
+}
+
+qint64 QAudioInputPrivate::totalTime() const
+{
+ return totalTimeValue;
+}
+
+void QAudioInputPrivate::suspend()
+{
+ if(deviceState == QAudio::ActiveState) {
+ waveInReset(hWaveIn);
+ deviceState = QAudio::SuspendState;
+ emit stateChanged(deviceState);
+ }
+}
+
+void QAudioInputPrivate::feedback()
+{
+#ifdef DEBUG_AUDIO
+ QTime now(QTime::currentTime());
+ qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT";
+#endif
+ bytesAvailable = bytesReady();
+
+ if(!(deviceState==QAudio::StopState||deviceState==QAudio::SuspendState))
+ emit processMore();
+}
+
+bool QAudioInputPrivate::deviceReady()
+{
+#ifdef DEBUG_AUDIO
+ QTime now(QTime::currentTime());
+ qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT";
+#endif
+ if(pullMode) {
+ // reads some audio data and writes it to QIODevice
+ read(0,0);
+ } else {
+ // emits readyRead() so user will call read() on QIODevice to get some audio data
+ InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
+ a->trigger();
+ }
+ if(deviceState != QAudio::ActiveState)
+ return true;
+
+ if(timeStamp.elapsed() > intervalTime && intervalTime > 50) {
+ emit notify();
+ timeStamp.restart();
+ }
+ return true;
+}
+
+qint64 QAudioInputPrivate::clock() const
+{
+ if(deviceState != QAudio::ActiveState)
+ return 0;
+
+ return timeStampOpened.elapsed();
+}
+
+void QAudioInputPrivate::reset()
+{
+ close();
+}
+
+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)
+ 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();
+}
+
diff --git a/src/multimedia/audio/qaudioinput_win32_p.h b/src/multimedia/audio/qaudioinput_win32_p.h
new file mode 100644
index 0000000..32464f0
--- /dev/null
+++ b/src/multimedia/audio/qaudioinput_win32_p.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+
+static CRITICAL_SECTION waveInCriticalSection;
+
+class QAudioInputPrivate : public QAbstractAudioInput
+{
+ Q_OBJECT
+public:
+ QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat);
+ ~QAudioInputPrivate();
+
+ qint64 read(char* data, qint64 len);
+
+ QAudioFormat format() const;
+ QIODevice* start(QIODevice* device = 0);
+ 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 totalTime() const;
+ qint64 clock() 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;
+ QTime timeStampOpened;
+ qint64 totalTimeValue;
+ bool pullMode;
+ bool resuming;
+ WAVEFORMATEX wfx;
+ HWAVEIN hWaveIn;
+ MMRESULT result;
+ WAVEHDR* waveBlocks;
+ volatile int waveFreeBlockCount;
+ int waveCurrentBlock;
+
+ static void 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;
+};
+
+#endif
diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp
new file mode 100644
index 0000000..785da61
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+#include <QtMultimedia/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 4.6
+
+ 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 QAudioDeviceId. 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:
+
+ \code
+ QFile inputFile;
+ inputFile.setFileName("/tmp/test.raw");
+ inputFile.open(QIODevice::ReadOnly);
+
+ QAudioFormat format;
+ // Set up the format, eg.
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+
+ QAudioOutput *audio = new QAudioOutput(format, this);
+ connect(audio,SIGNAL(stateChanged(QAudio::State)),SLOT(finishedPlaying(QAudio::State)));
+ audio->start(inputFile);
+
+ \endcode
+
+ 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:
+
+ \code
+ void finishedPlaying(QAudio::State state)
+ {
+ if(state == QAudio::IdleState) {
+ audio->stop();
+ inputFile.close();
+ }
+ }
+ \endcode
+
+ 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, clock() 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.
+
+ If an error is encountered state changes to QAudio::StopState.
+
+ \sa QAudioInput, QAudioDeviceInfo
+*/
+
+/*!
+ Construct a new audio output and attach it to \a parent.
+ The default audio output device is used with the output
+ \a format parameters.
+*/
+
+QAudioOutput::QAudioOutput(const QAudioFormat &format, QObject *parent):
+ QObject(parent)
+{
+ d = QAudioDeviceFactory::createDefaultOutputDevice(format);
+ connect(d, SIGNAL(notify()), SIGNAL(notify()));
+ connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
+}
+
+/*!
+ Construct a new audio output and attach it to \a parent.
+ The \a id of the audio output device is used with the output
+ \a format parameters.
+*/
+
+QAudioOutput::QAudioOutput(const QAudioDeviceId &id, const QAudioFormat &format, QObject *parent):
+ QObject(parent)
+{
+ d = QAudioDeviceFactory::createOutputDevice(id, format);
+ connect(d, SIGNAL(notify()), SIGNAL(notify()));
+ connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
+}
+
+/*!
+ Destroys this audio output.
+*/
+
+QAudioOutput::~QAudioOutput()
+{
+ delete d;
+}
+
+/*!
+ Returns the QAudioFormat being used.
+
+*/
+
+QAudioFormat QAudioOutput::format() const
+{
+ return d->format();
+}
+
+/*!
+ Uses the \a device as the QIODevice to transfer data.
+ If \a device is null then the class creates an internal QIODevice.
+ Returns a pointer to the QIODevice being used to handle the data
+ transfer. This QIODevice can be used to write() audio data
+ directly.
+ Passing a QIODevice allows the data to be transfered without any extra code.
+ All that is required is to open the QIODevice.
+
+ /sa QIODevice
+*/
+
+QIODevice* QAudioOutput::start(QIODevice* device)
+{
+ /*
+ PULL MODE (valid QIODevice)
+ -If currently not StopState, stop.
+ -If previous start was push mode, delete internal QIODevice.
+ -open audio output.
+ -If ok, NoError and ActiveState, else OpenError and StopState
+ -emit stateChanged()
+ -return device
+
+ PUSH MODE (device = 0)
+ -If currently not StopState, stop.
+ -If no internal QIODevice, create one.
+ -open audio output.
+ -If ok, NoError and IdleState, else OpenError and StopState
+ -emit stateChanged()
+ -return internal QIODevice
+ */
+ return d->start(device);
+}
+
+/*!
+ Stops the audio output.
+*/
+
+void QAudioOutput::stop()
+{
+ /*
+ -If StopState, return
+ -set to StopState
+ -detach from audio device
+ -emit stateChanged()
+ */
+ d->stop();
+}
+
+/*!
+ Drops all audio data in the buffers, resets buffers to zero.
+*/
+
+void QAudioOutput::reset()
+{
+ /*
+ -drop all buffered audio, set buffers to zero.
+ -call stop()
+ */
+ d->reset();
+}
+
+/*!
+ Stops processing audio data, preserving buffered audio data.
+*/
+
+void QAudioOutput::suspend()
+{
+ /*
+ -If not ActiveState|IdleState, return
+ -stop processing audio, saving all buffered audio data
+ -set NoError and SuspendState
+ -emit stateChanged()
+ */
+ d->suspend();
+}
+
+/*!
+ Resumes processing audio data after a suspend().
+*/
+
+void QAudioOutput::resume()
+{
+ /*
+ -If SuspendState, return
+ -resume audio
+ -(PULL MODE): set ActiveState, NoError
+ -(PUSH MODE): set IdleState, NoError
+ -kick start audio if needed
+ -emit stateChanged()
+ */
+ d->resume();
+}
+
+/*!
+ Returns the free space available in bytes in the audio buffer.
+*/
+
+int QAudioOutput::bytesFree() const
+{
+ /*
+ -If not ActiveState|IdleState, return 0
+ -return space available in audio buffer in bytes
+ */
+ return d->bytesFree();
+}
+
+/*!
+ Returns the period size in bytes.
+
+ Note: This is the recommended write size in bytes.
+*/
+
+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, calling bufferSize() anytime after start()
+ will return the actual buffer size being used.
+*/
+
+void QAudioOutput::setBufferSize(int value)
+{
+ d->setBufferSize(value);
+}
+
+/*!
+ Returns the audio buffer size in bytes.
+
+ If called before start(), returns platform default value.
+ If called before start() but setBufferSize() was called prior, returns value set by setBufferSize().
+ If called after start(), returns the actual buffer size being used. This may not be what was set previously
+ by setBufferSize().
+
+*/
+
+int QAudioOutput::bufferSize() const
+{
+ return d->bufferSize();
+}
+
+/*!
+ Sets the interval for notify() signal to be emitted.
+ This is based on the \a ms of audio data processed
+ not on actual real-time. The resolution of the timer is platform specific.
+*/
+
+void QAudioOutput::setNotifyInterval(int ms)
+{
+ d->setNotifyInterval(ms);
+}
+
+/*!
+ Returns the notify interval in milliseconds.
+*/
+
+int QAudioOutput::notifyInterval() const
+{
+ return d->notifyInterval();
+}
+
+/*!
+ Returns the amount of audio data processed since start()
+ was called in microseconds.
+*/
+
+qint64 QAudioOutput::totalTime() const
+{
+ return d->totalTime();
+}
+
+/*!
+ Returns the microseconds since start() was called, including time in Idle and
+ Suspend states.
+*/
+
+qint64 QAudioOutput::clock() const
+{
+ return d->clock();
+}
+
+/*!
+ Returns the error state.
+*/
+
+QAudio::Error QAudioOutput::error() const
+{
+ return d->error();
+}
+
+/*!
+ Returns the state of audio processing.
+*/
+
+QAudio::State QAudioOutput::state() const
+{
+ return d->state();
+}
+
+/*!
+ \fn QAudioOutput::stateChanged(QAudio::State state)
+ This signal is emitted when the device \a state has changed.
+ This is the current state of the audio output.
+*/
+
+/*!
+ \fn QAudioOutput::notify()
+ This signal is emitted when x ms of audio data has been processed
+ the interval set by setNotifyInterval(x).
+*/
+
+QT_END_NAMESPACE
diff --git a/src/multimedia/audio/qaudiooutput.h b/src/multimedia/audio/qaudiooutput.h
new file mode 100644
index 0000000..95e28ea
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QAUDIOOUTPUT_H
+#define QAUDIOOUTPUT_H
+
+#include <QtCore/qiodevice.h>
+#include <QtCore/qglobal.h>
+
+#include <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qaudiodeviceid.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 QAudioDeviceId &id, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
+ ~QAudioOutput();
+
+ QAudioFormat format() const;
+
+ QIODevice* start(QIODevice *device = 0);
+ 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 totalTime() const;
+ qint64 clock() const;
+
+ QAudio::Error error() const;
+ QAudio::State state() 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
diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/audio/qaudiooutput_alsa_p.cpp
new file mode 100644
index 0000000..d41c449
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput_alsa_p.cpp
@@ -0,0 +1,706 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#include <QtCore/qcoreapplication.h>
+#include "qaudiooutput_alsa_p.h"
+
+//#define DEBUG_AUDIO 1
+
+QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
+ settings(audioFormat)
+{
+ 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::StopState;
+ audioSource = 0;
+ pullMode = true;
+ resuming = false;
+ opened = false;
+
+ QStringList list1 = QString(tr(device)).split(tr(":"));
+ m_device = QByteArray(list1.at(0).toLocal8Bit().constData());
+
+ 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;
+ err = snd_pcm_prepare(handle);
+ if(err < 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 QAudioOutputPrivate::setFormat()
+{
+ snd_pcm_format_t pcmformat = SND_PCM_FORMAT_S16;
+
+ 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 snd_pcm_hw_params_set_format( handle, hwparams, pcmformat);
+}
+
+QIODevice* QAudioOutputPrivate::start(QIODevice* device)
+{
+ if(deviceState != QAudio::StopState)
+ deviceState = QAudio::StopState;
+
+ errorState = QAudio::NoError;
+
+ // Handle change of mode
+ if(audioSource && pullMode && !device) {
+ // pull -> push
+ close();
+ audioSource = 0;
+ } else if(audioSource && !pullMode && device) {
+ // push -> pull
+ close();
+ delete audioSource;
+ audioSource = 0;
+ }
+
+ if(device) {
+ //set to pull mode
+ pullMode = true;
+ audioSource = device;
+ deviceState = QAudio::ActiveState;
+ } else {
+ //set to push mode
+ if(!audioSource) {
+ 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::StopState)
+ return;
+ deviceState = QAudio::StopState;
+ 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();
+
+ int dir;
+ int err=-1;
+ int count=0;
+ unsigned int freakuency=settings.frequency();
+
+ QString dev = tr(m_device.constData());
+ if(!dev.contains(tr("default"))) {
+ dev = QString(tr("default:CARD=%1")).arg(tr(m_device.constData()));
+ }
+ // 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;
+ deviceState = QAudio::StopState;
+ 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(tr("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(tr("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(tr("QAudioOutput: snd_pcm_hw_params_set_access: err = %1")).arg(err);
+ }
+ }
+ if ( !fatal ) {
+ err = setFormat();
+ if ( err < 0 ) {
+ fatal = true;
+ errMessage = QString(tr("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(tr("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(tr("QAudioOutput: 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(tr("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(tr("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(tr("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(tr("QAudioOutput: snd_pcm_hw_params: err = %1")).arg(err);
+ }
+ }
+ if( err < 0) {
+ qWarning()<<errMessage;
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ 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);
+
+ errorState = QAudio::NoError;
+ totalTimeValue = 0;
+ opened = true;
+
+ return true;
+}
+
+void QAudioOutputPrivate::close()
+{
+ deviceState = QAudio::StopState;
+ 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((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*1000000/settings.frequency();
+ resuming = false;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ return snd_pcm_frames_to_bytes( handle, err );
+ } else
+ err = xrun_recovery(err);
+
+ if(err < 0) {
+ close();
+ errorState = QAudio::FatalError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ }
+ return 0;
+}
+
+int QAudioOutputPrivate::periodSize() const
+{
+ return period_size;
+}
+
+void QAudioOutputPrivate::setBufferSize(int value)
+{
+ if(deviceState == QAudio::StopState)
+ buffer_size = value;
+}
+
+int QAudioOutputPrivate::bufferSize() const
+{
+ return buffer_size;
+}
+
+void QAudioOutputPrivate::setNotifyInterval(int ms)
+{
+ intervalTime = ms;
+}
+
+int QAudioOutputPrivate::notifyInterval() const
+{
+ return intervalTime;
+}
+
+qint64 QAudioOutputPrivate::totalTime() const
+{
+ return totalTimeValue;
+}
+
+void QAudioOutputPrivate::resume()
+{
+ if(deviceState == QAudio::SuspendState) {
+ 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;
+ if(pullMode)
+ deviceState = QAudio::ActiveState;
+ else
+ deviceState = QAudio::IdleState;
+
+ errorState = QAudio::NoError;
+ timer->start(period_time/1000);
+ emit stateChanged(deviceState);
+ }
+}
+
+QAudioFormat QAudioOutputPrivate::format() const
+{
+ return settings;
+}
+
+void QAudioOutputPrivate::suspend()
+{
+ if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState || resuming) {
+ timer->stop();
+ deviceState = QAudio::SuspendState;
+ errorState = QAudio::NoError;
+ emit stateChanged(deviceState);
+ }
+}
+
+void QAudioOutputPrivate::userFeed()
+{
+ if(deviceState == QAudio::StopState || deviceState == QAudio::SuspendState)
+ 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()
+{
+ QMetaObject::invokeMethod(this, SLOT(updateAvailable()), Qt::QueuedConnection);
+}
+
+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;
+ write(audioBuffer,l);
+ 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
+ errorState = QAudio::UnderrunError;
+ deviceState = QAudio::IdleState;
+ emit stateChanged(deviceState);
+ }
+
+ } else if(l < 0) {
+ close();
+ errorState = QAudio::IOError;
+ emit stateChanged(deviceState);
+ }
+ } else
+ bytesAvailable = bytesFree();
+
+ if(deviceState != QAudio::ActiveState)
+ return true;
+
+ if(timeStamp.elapsed() > intervalTime && intervalTime > 50) {
+ emit notify();
+ timeStamp.restart();
+ }
+ return true;
+}
+
+qint64 QAudioOutputPrivate::clock() const
+{
+ if(!handle)
+ return 0;
+
+ if(deviceState != QAudio::ActiveState)
+ return 0;
+
+ snd_pcm_status_t* status;
+ snd_pcm_status_alloca(&status);
+
+ snd_timestamp_t t1,t2;
+ if( snd_pcm_status(handle, status) >= 0) {
+ snd_pcm_status_get_tstamp(status,&t1);
+ snd_pcm_status_get_trigger_tstamp(status,&t2);
+ t1.tv_sec-=t2.tv_sec;
+
+ signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec;
+ if(l < 0) {
+ t1.tv_sec--;
+ l = -l;
+ l %= 1000000;
+ }
+ return ((t1.tv_sec * 1000)+l/1000);
+ } else
+ return 0;
+ return 0;
+}
+
+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;
+
+}
diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.h b/src/multimedia/audio/qaudiooutput_alsa_p.h
new file mode 100644
index 0000000..f243bad
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput_alsa_p.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+class OutputPrivate;
+
+class QAudioOutputPrivate : public QAbstractAudioOutput
+{
+ friend class OutputPrivate;
+ Q_OBJECT
+public:
+ QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat);
+ ~QAudioOutputPrivate();
+
+ qint64 write( const char *data, qint64 len );
+
+ QIODevice* start(QIODevice* device = 0);
+ 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 totalTime() const;
+ qint64 clock() const;
+ QAudio::Error error() const;
+ QAudio::State state() const;
+ 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;
+ 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;
+};
+
+#endif
diff --git a/src/multimedia/audio/qaudiooutput_mac_p.cpp b/src/multimedia/audio/qaudiooutput_mac_p.cpp
new file mode 100644
index 0000000..0d6e615
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput_mac_p.cpp
@@ -0,0 +1,700 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#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 <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudiooutput.h>
+
+#include "qaudio_mac_p.h"
+#include "qaudiooutput_mac_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+
+namespace
+{
+
+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) {
+ region.second -= region.second % m_bytesPerFrame;
+ memcpy(data + (framesRead * m_bytesPerFrame), region.first, region.second);
+ framesRead += region.second / m_bytesPerFrame;
+ }
+ 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_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(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:
+ QAudioOutputBuffer* m_audioBuffer;
+};
+
+
+QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray& device, const QAudioFormat& format):
+ audioFormat(format)
+{
+ QDataStream ds(device);
+ quint32 did, mode;
+
+ ds >> did >> mode;
+
+ if (QAudio::Mode(mode) == QAudio::AudioInput)
+ errorCode = QAudio::OpenError;
+ else {
+ isOpen = false;
+ audioDeviceId = AudioDeviceID(did);
+ audioUnit = 0;
+ audioIO = 0;
+ startTime = 0;
+ totalFrames = 0;
+ audioBuffer = 0;
+ internalBufferSize = default_buffer_size;
+ clockFrequency = AudioGetHostClockFrequency() / 1000;
+ errorCode = QAudio::NoError;
+ stateCode = QAudio::StopState;
+ audioThreadState = Stopped;
+
+ intervalTimer = new QTimer(this);
+ intervalTimer->setInterval(1000);
+ connect(intervalTimer, SIGNAL(timeout()), SIGNAL(notify()));
+ }
+}
+
+QAudioOutputPrivate::~QAudioOutputPrivate()
+{
+ 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(deviceFormat);
+ if (AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input,
+ 0,
+ &deviceFormat,
+ &size) != noErr) {
+ qWarning() << "QAudioOutput: Unable to retrieve device format";
+ return false;
+ }
+
+ 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.mSampleRate / deviceFormat.mSampleRate) *
+ streamFormat.mBytesPerFrame;
+ if (internalBufferSize < periodSizeBytes * 2)
+ internalBufferSize = periodSizeBytes * 2;
+ else
+ internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
+
+ audioBuffer = new 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;
+}
+
+QIODevice* QAudioOutputPrivate::start(QIODevice* device)
+{
+ QIODevice* op = device;
+
+ if (!open()) {
+ stateCode = QAudio::StopState;
+ errorCode = QAudio::OpenError;
+ return audioIO;
+ }
+
+ 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();
+
+ return op;
+}
+
+void QAudioOutputPrivate::stop()
+{
+ QMutexLocker lock(&mutex);
+ if (stateCode != QAudio::StopState) {
+ audioThreadDrain();
+
+ stateCode = QAudio::StopState;
+ errorCode = QAudio::NoError;
+ QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
+ }
+}
+
+void QAudioOutputPrivate::reset()
+{
+ QMutexLocker lock(&mutex);
+ if (stateCode != QAudio::StopState) {
+ audioThreadStop();
+
+ stateCode = QAudio::StopState;
+ 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::SuspendState;
+ errorCode = QAudio::NoError;
+ QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
+ }
+}
+
+void QAudioOutputPrivate::resume()
+{
+ QMutexLocker lock(&mutex);
+ if (stateCode == QAudio::SuspendState) {
+ 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::StopState)
+ internalBufferSize = bs;
+}
+
+int QAudioOutputPrivate::bufferSize() const
+{
+ return internalBufferSize;
+}
+
+void QAudioOutputPrivate::setNotifyInterval(int milliSeconds)
+{
+ intervalTimer->setInterval(milliSeconds);
+}
+
+int QAudioOutputPrivate::notifyInterval() const
+{
+ return intervalTimer->interval();
+}
+
+qint64 QAudioOutputPrivate::totalTime() const
+{
+ return totalFrames * 1000000 / audioFormat.frequency();
+}
+
+qint64 QAudioOutputPrivate::clock() const
+{
+ 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::StopState;
+ QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
+ }
+}
+
+void QAudioOutputPrivate::startTimers()
+{
+ audioBuffer->startFillTimer();
+ 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"
+
diff --git a/src/multimedia/audio/qaudiooutput_mac_p.h b/src/multimedia/audio/qaudiooutput_mac_p.h
new file mode 100644
index 0000000..c85cab4
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput_mac_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudioformat.h>
+#include <QtMultimedia/qaudioengine.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+namespace
+{
+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;
+ QAudioOutputBuffer* audioBuffer;
+ QAtomicInt audioThreadState;
+ QWaitCondition threadFinished;
+ QMutex mutex;
+ QTimer* intervalTimer;
+
+ QAudio::Error errorCode;
+ QAudio::State stateCode;
+
+ QAudioOutputPrivate(const QByteArray& device, const QAudioFormat& format);
+ ~QAudioOutputPrivate();
+
+ bool open();
+ void close();
+
+ QAudioFormat format() const;
+
+ QIODevice* 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 totalTime() const;
+ qint64 clock() 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();
+
+signals:
+ void stateChanged(QAudio::State);
+ void notify();
+
+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
diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp
new file mode 100644
index 0000000..f681936
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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.
+//
+
+#include "qaudiooutput_win32_p.h"
+
+//#define DEBUG_AUDIO 1
+
+QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
+ settings(audioFormat)
+{
+ bytesAvailable = 0;
+ buffer_size = 0;
+ period_size = 0;
+ m_device = device;
+ totalTimeValue = 0;
+ intervalTime = 1000;
+ audioBuffer = 0;
+ errorState = QAudio::NoError;
+ deviceState = QAudio::StopState;
+ audioSource = 0;
+ pullMode = true;
+ InitializeCriticalSection(&waveOutCriticalSection);
+}
+
+QAudioOutputPrivate::~QAudioOutputPrivate()
+{
+ close();
+ DeleteCriticalSection(&waveOutCriticalSection);
+}
+
+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;
+
+ switch(uMsg) {
+ case WOM_OPEN:
+ qAudio->feedback();
+ break;
+ case WOM_CLOSE:
+ return;
+ case WOM_DONE:
+ EnterCriticalSection(&waveOutCriticalSection);
+ qAudio->waveFreeBlockCount++;
+ if(qAudio->waveFreeBlockCount >= qAudio->buffer_size/qAudio->period_size)
+ qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size;
+ LeaveCriticalSection(&waveOutCriticalSection);
+ 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)
+{
+ HeapFree(GetProcessHeap(), 0, blockArray);
+}
+
+QAudioFormat QAudioOutputPrivate::format() const
+{
+ return settings;
+}
+
+QIODevice* QAudioOutputPrivate::start(QIODevice* device)
+{
+ if(deviceState != QAudio::StopState)
+ close();
+
+ if(!pullMode && audioSource) {
+ delete audioSource;
+ }
+
+ if(device) {
+ //set to pull mode
+ pullMode = true;
+ audioSource = device;
+ deviceState = QAudio::ActiveState;
+ } else {
+ //set to push mode
+ 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::StopState)
+ return;
+ deviceState = QAudio::StopState;
+ 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
+ if(buffer_size == 0) {
+ // Default buffer size, 200ms, default period size is 40ms
+ buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2;
+ period_size = buffer_size/5;
+ } else {
+ period_size = buffer_size/5;
+ }
+ waveBlocks = allocateBlocks(period_size, buffer_size/period_size);
+ waveFreeBlockCount = buffer_size/period_size;
+ waveCurrentBlock = 0;
+
+ if(audioBuffer == 0)
+ audioBuffer = new char[buffer_size];
+
+ timeStamp.restart();
+
+ 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;
+
+ UINT_PTR devId = WAVE_MAPPER;
+
+ WAVEOUTCAPS woc;
+ unsigned long iNumDevs,ii;
+ iNumDevs = waveOutGetNumDevs();
+ for(ii=0;ii<iNumDevs;ii++) {
+ if(waveOutGetDevCaps(ii, &woc, sizeof(WAVEOUTCAPS))
+ == MMSYSERR_NOERROR) {
+ QString tmp;
+ tmp = QString::fromUtf16((const unsigned short*)woc.szPname);
+ if(tmp.compare(tr(m_device)) == 0) {
+ devId = ii;
+ break;
+ }
+ }
+ }
+
+ if(waveOutOpen(&hWaveOut, devId, &wfx,
+ (DWORD_PTR)&waveOutProc,
+ (DWORD_PTR) this,
+ CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
+ errorState = QAudio::OpenError;
+ deviceState = QAudio::StopState;
+ emit stateChanged(deviceState);
+ qWarning("QAudioOutput: open error");
+ return false;
+ }
+
+ totalTimeValue = 0;
+ timeStampOpened.restart();
+
+ 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::StopState)
+ return;
+
+ deviceState = QAudio::StopState;
+ 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::StopState)
+ buffer_size = value;
+}
+
+int QAudioOutputPrivate::bufferSize() const
+{
+ return buffer_size;
+}
+
+void QAudioOutputPrivate::setNotifyInterval(int ms)
+{
+ intervalTime = ms;
+}
+
+int QAudioOutputPrivate::notifyInterval() const
+{
+ return intervalTime;
+}
+
+qint64 QAudioOutputPrivate::totalTime() const
+{
+ return totalTimeValue;
+}
+
+qint64 QAudioOutputPrivate::write( const char *data, qint64 len )
+{
+ // Write out some audio data
+
+ char* p = (char*)data;
+ int l = (int)len;
+
+ WAVEHDR* current;
+ int remain;
+ current = &waveBlocks[waveCurrentBlock];
+ while(l > 0) {
+ if(waveFreeBlockCount==0)
+ break;
+
+ 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));
+
+ EnterCriticalSection(&waveOutCriticalSection);
+ waveFreeBlockCount--;
+ LeaveCriticalSection(&waveOutCriticalSection);
+#ifdef DEBUG_AUDIO
+ qDebug("write out l=%d, waveFreeBlockCount=%d",
+ current->dwBufferLength,waveFreeBlockCount);
+#endif
+ totalTimeValue += current->dwBufferLength
+ /(settings.channels()*(settings.sampleSize()/8))
+ *1000000/settings.frequency();;
+ waveCurrentBlock++;
+ waveCurrentBlock %= buffer_size/period_size;
+ current = &waveBlocks[waveCurrentBlock];
+ current->dwUser = 0;
+ }
+ return (len-l);
+}
+
+void QAudioOutputPrivate::resume()
+{
+ if(deviceState == QAudio::SuspendState) {
+ deviceState = QAudio::ActiveState;
+ errorState = QAudio::NoError;
+ waveOutRestart(hWaveOut);
+ QTimer::singleShot(10, this, SLOT(feedback()));
+ emit stateChanged(deviceState);
+ }
+}
+
+void QAudioOutputPrivate::suspend()
+{
+ if(deviceState == QAudio::ActiveState) {
+ waveOutPause(hWaveOut);
+ deviceState = QAudio::SuspendState;
+ 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::StopState||deviceState==QAudio::SuspendState)) {
+ if(bytesAvailable >= period_size)
+ QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection);
+ }
+}
+
+bool QAudioOutputPrivate::deviceReady()
+{
+ if(pullMode) {
+ int i = 0;
+ 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;
+
+ 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)
+ deviceState = QAudio::ActiveState;
+ if(startup)
+ waveOutRestart(hWaveOut);
+ } else if(l == 0) {
+ bytesAvailable = bytesFree();
+ if(waveFreeBlockCount == buffer_size/period_size) {
+ errorState = QAudio::UnderrunError;
+ deviceState = QAudio::IdleState;
+ emit stateChanged(deviceState);
+ }
+
+ } else if(i < 0) {
+ bytesAvailable = bytesFree();
+ errorState = QAudio::IOError;
+ }
+ }
+ if(deviceState != QAudio::ActiveState)
+ return true;
+
+ if(timeStamp.elapsed() > intervalTime && intervalTime > 50) {
+ emit notify();
+ timeStamp.restart();
+ }
+
+ return true;
+}
+
+qint64 QAudioOutputPrivate::clock() const
+{
+ if(deviceState != QAudio::ActiveState)
+ return 0;
+
+ return timeStampOpened.elapsed();
+}
+
+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;
+}
diff --git a/src/multimedia/audio/qaudiooutput_win32_p.h b/src/multimedia/audio/qaudiooutput_win32_p.h
new file mode 100644
index 0000000..91f14f5
--- /dev/null
+++ b/src/multimedia/audio/qaudiooutput_win32_p.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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 <QtMultimedia/qaudio.h>
+#include <QtMultimedia/qaudiodeviceinfo.h>
+#include <QtMultimedia/qaudioengine.h>
+
+
+static CRITICAL_SECTION waveOutCriticalSection;
+
+class QAudioOutputPrivate : public QAbstractAudioOutput
+{
+ Q_OBJECT
+public:
+ QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat);
+ ~QAudioOutputPrivate();
+
+ qint64 write( const char *data, qint64 len );
+
+ QAudioFormat format() const;
+ QIODevice* start(QIODevice* device = 0);
+ 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 totalTime() const;
+ qint64 clock() 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();
+
+signals:
+ void stateChanged(QAudio::State);
+ void notify();
+
+private:
+ QByteArray m_device;
+ bool resuming;
+ int bytesAvailable;
+ QTime timeStamp;
+ QTime timeStampOpened;
+ qint32 buffer_size;
+ qint32 period_size;
+ qint64 totalTimeValue;
+ bool pullMode;
+ int intervalTime;
+ static void CALLBACK waveOutProc( HWAVEOUT hWaveOut, UINT uMsg,
+ DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
+
+ 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 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;
+};
+
+#endif
diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro
new file mode 100644
index 0000000..7d38afa
--- /dev/null
+++ b/src/multimedia/multimedia.pro
@@ -0,0 +1,11 @@
+TARGET = QtMultimedia
+QPRO_PWD = $$PWD
+QT = core
+DEFINES += QT_BUILD_MULTIMEDIA_LIB
+
+win32-msvc*:QMAKE_LIBS += $$QMAKE_LIBS_CORE
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore
+
+include(../qbase.pri)
+include(audio/audio.pri)
diff --git a/src/plugins/audio/audio.pro b/src/plugins/audio/audio.pro
new file mode 100644
index 0000000..e93b369
--- /dev/null
+++ b/src/plugins/audio/audio.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+#SUBDIRS += ossaudio
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index cf4edf1..45669e4 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -10,3 +10,4 @@ unix {
embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers
!win32:!embedded:!mac:SUBDIRS *= inputmethods
contains(QT_CONFIG, phonon): SUBDIRS *= phonon
+contains(QT_CONFIG, multimedia): SUBDIRS *= audio
diff --git a/src/src.pro b/src/src.pro
index 34db728..54ed6da 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -22,6 +22,7 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, o
contains(QT_CONFIG, openvg): SRC_SUBDIRS += src_openvg
contains(QT_CONFIG, xmlpatterns): SRC_SUBDIRS += src_xmlpatterns
contains(QT_CONFIG, phonon): SRC_SUBDIRS += src_phonon
+contains(QT_CONFIG, multimedia): SRC_SUBDIRS += src_multimedia
contains(QT_CONFIG, svg): SRC_SUBDIRS += src_svg
contains(QT_CONFIG, webkit) {
#exists($$QT_SOURCE_TREE/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pro): SRC_SUBDIRS += src_javascriptcore
@@ -68,6 +69,8 @@ src_qt3support.subdir = $$QT_SOURCE_TREE/src/qt3support
src_qt3support.target = sub-qt3support
src_phonon.subdir = $$QT_SOURCE_TREE/src/phonon
src_phonon.target = sub-phonon
+src_multimedia.subdir = $$QT_SOURCE_TREE/src/multimedia
+src_multimedia.target = sub-multimedia
src_tools_uic3.subdir = $$QT_SOURCE_TREE/src/tools/uic3
src_tools_uic3.target = sub-uic3
src_activeqt.subdir = $$QT_SOURCE_TREE/src/activeqt
@@ -104,6 +107,7 @@ src_webkit.target = sub-webkit
src_testlib.depends = src_corelib
src_qt3support.depends = src_gui src_xml src_network src_sql
src_phonon.depends = src_gui
+ src_multimedia.depends = src_gui
src_tools_uic3.depends = src_qt3support src_xml
src_tools_idc.depends = src_corelib
src_tools_activeqt.depends = src_tools_idc src_gui
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index b4a6600..2550dcd 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -284,6 +284,10 @@ SUBDIRS += _networkselftest \
qsocks5socketengine \
qsortfilterproxymodel \
qsound \
+ qaudiodeviceid \
+ qaudioformat \
+ qaudiooutput \
+ qaudioinput \
qspinbox \
qsplitter \
qsql \
diff --git a/tests/auto/qaudiodeviceid/qaudiodeviceid.pro b/tests/auto/qaudiodeviceid/qaudiodeviceid.pro
new file mode 100644
index 0000000..e0c7d4d
--- /dev/null
+++ b/tests/auto/qaudiodeviceid/qaudiodeviceid.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
+
+SOURCES += tst_qaudiodeviceid.cpp
+
+QT = core multimedia
diff --git a/tests/auto/qaudiodeviceid/tst_qaudiodeviceid.cpp b/tests/auto/qaudiodeviceid/tst_qaudiodeviceid.cpp
new file mode 100644
index 0000000..d40118b
--- /dev/null
+++ b/tests/auto/qaudiodeviceid/tst_qaudiodeviceid.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudiodeviceid.h>
+#include <qaudiodeviceinfo.h>
+
+#include <QStringList>
+#include <QList>
+
+
+class tst_QAudioDeviceId : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAudioDeviceId(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void checkNull();
+ void checkEquality();
+};
+
+void tst_QAudioDeviceId::checkNull()
+{
+ // Default constructed is null.
+ QAudioDeviceId deviceId0;
+ QVERIFY(deviceId0.isNull());
+
+ // Null is transferred
+ QAudioDeviceId deviceId1(deviceId0);
+ QVERIFY(deviceId1.isNull());
+}
+
+void tst_QAudioDeviceId::checkEquality()
+{
+ QAudioDeviceId deviceId0;
+ QAudioDeviceId deviceId1;
+
+ // Null ids are equivalent
+ QVERIFY(deviceId0 == deviceId1);
+ QVERIFY(!(deviceId0 != deviceId1));
+
+ deviceId1 = QAudioDeviceInfo::defaultOutputDevice();
+
+ // Different
+ QVERIFY(deviceId0 != deviceId1);
+ QVERIFY(!(deviceId0 == deviceId1));
+
+ // Same
+ deviceId0 = deviceId1;
+
+ QVERIFY(deviceId0 == deviceId1);
+ QVERIFY(!(deviceId0 != deviceId1));
+}
+
+QTEST_MAIN(tst_QAudioDeviceId)
+
+#include "tst_qaudiodeviceid.moc"
diff --git a/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro b/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro
new file mode 100644
index 0000000..695987c
--- /dev/null
+++ b/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
+
+SOURCES += tst_qaudiodeviceinfo.cpp
+
+QT = core multimedia
diff --git a/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp b/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
new file mode 100644
index 0000000..c2cd97e
--- /dev/null
+++ b/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudiodeviceinfo.h>
+
+#include <QStringList>
+#include <QList>
+
+
+class tst_QAudioDeviceInfo : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAudioDeviceInfo(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void checkAvailableDefaultInput();
+ void checkAvailableDefaultOutput();
+ void outputList();
+ void codecs();
+ void channels();
+ void sampleSizes();
+ void byteOrders();
+ void sampleTypes();
+ void frequencies();
+ void isformat();
+ void preferred();
+ void nearest();
+
+private:
+ QAudioDeviceInfo* device;
+};
+
+void tst_QAudioDeviceInfo::checkAvailableDefaultInput()
+{
+ QVERIFY(!QAudioDeviceInfo::defaultInputDevice().isNull());
+}
+
+void tst_QAudioDeviceInfo::checkAvailableDefaultOutput()
+{
+ QVERIFY(!QAudioDeviceInfo::defaultOutputDevice().isNull());
+}
+
+void tst_QAudioDeviceInfo::outputList()
+{
+ QList<QAudioDeviceId> devices = QAudioDeviceInfo::deviceList(QAudio::AudioOutput);
+ QVERIFY(devices.size() > 0);
+ device = new QAudioDeviceInfo(devices.at(0), this);
+}
+
+void tst_QAudioDeviceInfo::codecs()
+{
+ QStringList avail = device->supportedCodecs();
+ QVERIFY(avail.size() > 0);
+}
+
+void tst_QAudioDeviceInfo::channels()
+{
+ QList<int> avail = device->supportedChannels();
+ QVERIFY(avail.size() > 0);
+}
+
+void tst_QAudioDeviceInfo::sampleSizes()
+{
+ QList<int> avail = device->supportedSampleSizes();
+ QVERIFY(avail.size() > 0);
+}
+
+void tst_QAudioDeviceInfo::byteOrders()
+{
+ QList<QAudioFormat::Endian> avail = device->supportedByteOrders();
+ QVERIFY(avail.size() > 0);
+}
+
+void tst_QAudioDeviceInfo::sampleTypes()
+{
+ QList<QAudioFormat::SampleType> avail = device->supportedSampleTypes();
+ QVERIFY(avail.size() > 0);
+}
+
+void tst_QAudioDeviceInfo::frequencies()
+{
+ QList<int> avail = device->supportedFrequencies();
+ QVERIFY(avail.size() > 0);
+}
+
+void tst_QAudioDeviceInfo::isformat()
+{
+ QAudioFormat format;
+ format.setFrequency(44100);
+ format.setChannels(2);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleSize(16);
+ format.setCodec("audio/pcm");
+
+ // Should always be true for these format
+ QVERIFY(device->isFormatSupported(format));
+}
+
+void tst_QAudioDeviceInfo::preferred()
+{
+ QAudioFormat format = device->preferredFormat();
+ QVERIFY(format.frequency() == 44100);
+ QVERIFY(format.channels() == 2);
+}
+
+void tst_QAudioDeviceInfo::nearest()
+{
+ QAudioFormat format1, format2;
+ format1.setFrequency(8000);
+ format2 = device->nearestFormat(format1);
+ QVERIFY(format2.frequency() == 44100);
+}
+
+QTEST_MAIN(tst_QAudioDeviceInfo)
+
+#include "tst_qaudiodeviceinfo.moc"
diff --git a/tests/auto/qaudioformat/qaudioformat.pro b/tests/auto/qaudioformat/qaudioformat.pro
new file mode 100644
index 0000000..78962d7
--- /dev/null
+++ b/tests/auto/qaudioformat/qaudioformat.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
+
+SOURCES += tst_qaudioformat.cpp
+
+QT = core multimedia
diff --git a/tests/auto/qaudioformat/tst_qaudioformat.cpp b/tests/auto/qaudioformat/tst_qaudioformat.cpp
new file mode 100644
index 0000000..bcfc78f
--- /dev/null
+++ b/tests/auto/qaudioformat/tst_qaudioformat.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudioformat.h>
+
+#include <QStringList>
+#include <QList>
+
+
+class tst_QAudioFormat : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAudioFormat(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void checkNull();
+ void checkFrequency();
+ void checkChannels();
+ void checkSampleSize();
+ void checkCodec();
+ void checkByteOrder();
+ void checkSampleType();
+ void checkEquality();
+ void checkAssignment();
+};
+
+void tst_QAudioFormat::checkNull()
+{
+ // Default constructed QAudioFormat is null.
+ QAudioFormat audioFormat0;
+ QVERIFY(audioFormat0.isNull());
+
+ // Null is transferred
+ QAudioFormat audioFormat1(audioFormat0);
+ QVERIFY(audioFormat1.isNull());
+
+ // Null is voided on activity
+ audioFormat0.setFrequency(44100);
+ QVERIFY(!audioFormat0.isNull());
+}
+
+void tst_QAudioFormat::checkFrequency()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setFrequency(44100);
+ QVERIFY(audioFormat.frequency() == 44100);
+}
+
+void tst_QAudioFormat::checkChannels()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setChannels(2);
+ QVERIFY(audioFormat.channels() == 2);
+}
+
+void tst_QAudioFormat::checkSampleSize()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setSampleSize(16);
+ QVERIFY(audioFormat.sampleSize() == 16);
+}
+
+void tst_QAudioFormat::checkCodec()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setCodec(QString::fromLatin1("audio/pcm"));
+ QVERIFY(audioFormat.codec() == QString::fromLatin1("audio/pcm"));
+}
+
+void tst_QAudioFormat::checkByteOrder()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setByteOrder(QAudioFormat::LittleEndian);
+ QVERIFY(audioFormat.byteOrder() == QAudioFormat::LittleEndian);
+}
+
+void tst_QAudioFormat::checkSampleType()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setSampleType(QAudioFormat::SignedInt);
+ QVERIFY(audioFormat.sampleType() == QAudioFormat::SignedInt);
+}
+
+void tst_QAudioFormat::checkEquality()
+{
+ QAudioFormat audioFormat0;
+ QAudioFormat audioFormat1;
+
+ // Null formats are equivalent
+ QVERIFY(audioFormat0 == audioFormat1);
+ QVERIFY(!(audioFormat0 != audioFormat1));
+
+ // on filled formats
+ audioFormat0.setFrequency(8000);
+ audioFormat0.setChannels(1);
+ audioFormat0.setSampleSize(8);
+ audioFormat0.setCodec("audio/pcm");
+ audioFormat0.setByteOrder(QAudioFormat::LittleEndian);
+ audioFormat0.setSampleType(QAudioFormat::UnSignedInt);
+
+ audioFormat1.setFrequency(8000);
+ audioFormat1.setChannels(1);
+ audioFormat1.setSampleSize(8);
+ audioFormat1.setCodec("audio/pcm");
+ audioFormat1.setByteOrder(QAudioFormat::LittleEndian);
+ audioFormat1.setSampleType(QAudioFormat::UnSignedInt);
+
+ QVERIFY(audioFormat0 == audioFormat1);
+ QVERIFY(!(audioFormat0 != audioFormat1));
+
+ audioFormat0.setFrequency(44100);
+ QVERIFY(audioFormat0 != audioFormat1);
+ QVERIFY(!(audioFormat0 == audioFormat1));
+}
+
+void tst_QAudioFormat::checkAssignment()
+{
+ QAudioFormat audioFormat0;
+ QAudioFormat audioFormat1;
+
+ audioFormat0.setFrequency(8000);
+ audioFormat0.setChannels(1);
+ audioFormat0.setSampleSize(8);
+ audioFormat0.setCodec("audio/pcm");
+ audioFormat0.setByteOrder(QAudioFormat::LittleEndian);
+ audioFormat0.setSampleType(QAudioFormat::UnSignedInt);
+
+ audioFormat1 = audioFormat0;
+ QVERIFY(audioFormat1 == audioFormat0);
+
+ QAudioFormat audioFormat2(audioFormat0);
+ QVERIFY(audioFormat2 == audioFormat0);
+}
+
+QTEST_MAIN(tst_QAudioFormat)
+
+#include "tst_qaudioformat.moc"
diff --git a/tests/auto/qaudioinput/qaudioinput.pro b/tests/auto/qaudioinput/qaudioinput.pro
new file mode 100644
index 0000000..8a03749
--- /dev/null
+++ b/tests/auto/qaudioinput/qaudioinput.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
+
+SOURCES += tst_qaudioinput.cpp
+
+QT = core multimedia
diff --git a/tests/auto/qaudioinput/tst_qaudioinput.cpp b/tests/auto/qaudioinput/tst_qaudioinput.cpp
new file mode 100644
index 0000000..6e16320
--- /dev/null
+++ b/tests/auto/qaudioinput/tst_qaudioinput.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudioinput.h>
+#include <qaudiodeviceinfo.h>
+#include <qaudio.h>
+#include <qaudioformat.h>
+
+
+class tst_QAudioInput : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAudioInput(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void initTestCase();
+ void settings();
+ void notifyInterval();
+ void pullFile();
+
+private:
+ QAudioFormat format;
+ QAudioInput* audio;
+};
+
+void tst_QAudioInput::initTestCase()
+{
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+
+ audio = new QAudioInput(format, this);
+}
+
+void tst_QAudioInput::settings()
+{
+ QAudioFormat f = audio->format();
+
+ QVERIFY(format.channels() == f.channels());
+ QVERIFY(format.frequency() == f.frequency());
+ QVERIFY(format.sampleSize() == f.sampleSize());
+ QVERIFY(format.codec() == f.codec());
+ QVERIFY(format.byteOrder() == f.byteOrder());
+ QVERIFY(format.sampleType() == f.sampleType());
+}
+
+void tst_QAudioInput::notifyInterval()
+{
+ QVERIFY(audio->notifyInterval() == 1000); // Default
+
+ audio->setNotifyInterval(500);
+ QVERIFY(audio->notifyInterval() == 500); // Custom
+
+ audio->setNotifyInterval(1000); // reset
+}
+
+void tst_QAudioInput::pullFile()
+{
+ QFile filename(SRCDIR "test.raw");
+ filename.open( QIODevice::WriteOnly | QIODevice::Truncate );
+
+ QSignalSpy readSignal(audio, SIGNAL(notify()));
+ audio->start(&filename);
+
+ QTest::qWait(5000);
+
+ QVERIFY(readSignal.count() > 0);
+ QVERIFY(audio->totalTime() > 0);
+
+ audio->stop();
+ filename.close();
+}
+
+QTEST_MAIN(tst_QAudioInput)
+
+#include "tst_qaudioinput.moc"
diff --git a/tests/auto/qaudiooutput/4.wav b/tests/auto/qaudiooutput/4.wav
new file mode 100644
index 0000000..e31b0609
--- /dev/null
+++ b/tests/auto/qaudiooutput/4.wav
Binary files differ
diff --git a/tests/auto/qaudiooutput/qaudiooutput.pro b/tests/auto/qaudiooutput/qaudiooutput.pro
new file mode 100644
index 0000000..6c07c64
--- /dev/null
+++ b/tests/auto/qaudiooutput/qaudiooutput.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
+
+SOURCES += tst_qaudiooutput.cpp
+
+QT = core multimedia
+
+wince*: {
+ deploy.sources += 4.wav
+ DEPLOYMENT = deploy
+}
diff --git a/tests/auto/qaudiooutput/tst_qaudiooutput.cpp b/tests/auto/qaudiooutput/tst_qaudiooutput.cpp
new file mode 100644
index 0000000..0f94faa
--- /dev/null
+++ b/tests/auto/qaudiooutput/tst_qaudiooutput.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudiooutput.h>
+#include <qaudiodeviceinfo.h>
+#include <qaudio.h>
+#include <qaudioformat.h>
+
+
+class tst_QAudioOutput : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAudioOutput(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void initTestCase();
+ void settings();
+ void notifyInterval();
+ void pullFile();
+ void pushFile();
+
+private:
+ QAudioFormat format;
+ QAudioOutput* audio;
+};
+
+void tst_QAudioOutput::initTestCase()
+{
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+
+ audio = new QAudioOutput(format, this);
+}
+
+void tst_QAudioOutput::settings()
+{
+ QAudioFormat f = audio->format();
+
+ QVERIFY(format.channels() == f.channels());
+ QVERIFY(format.frequency() == f.frequency());
+ QVERIFY(format.sampleSize() == f.sampleSize());
+ QVERIFY(format.codec() == f.codec());
+ QVERIFY(format.byteOrder() == f.byteOrder());
+ QVERIFY(format.sampleType() == f.sampleType());
+}
+
+void tst_QAudioOutput::notifyInterval()
+{
+ QVERIFY(audio->notifyInterval() == 1000); // Default
+
+ audio->setNotifyInterval(500);
+ QVERIFY(audio->notifyInterval() == 500); // Custom
+
+ audio->setNotifyInterval(1000); // reset
+}
+
+void tst_QAudioOutput::pullFile()
+{
+ QFile filename(SRCDIR "4.wav");
+ QVERIFY(filename.exists());
+ filename.open(QIODevice::ReadOnly);
+
+ QSignalSpy readSignal(audio, SIGNAL(notify()));
+ audio->setNotifyInterval(100);
+ audio->start(&filename);
+
+ QTestEventLoop::instance().enterLoop(1);
+ // 4.wav is a little less than 700ms, so notify should fire 6 times!
+ QVERIFY(readSignal.count() >= 6);
+ QVERIFY(audio->totalTime() == 692250);
+
+ audio->stop();
+ filename.close();
+}
+
+void tst_QAudioOutput::pushFile()
+{
+ QFile filename(SRCDIR "4.wav");
+ QVERIFY(filename.exists());
+ filename.open(QIODevice::ReadOnly);
+
+ const qint64 fileSize = filename.size();
+
+ QIODevice* feed = audio->start(0);
+
+ char* buffer = new char[fileSize];
+ filename.read(buffer, fileSize);
+
+ qint64 counter=0;
+ qint64 written=0;
+ while(written < fileSize) {
+ written+=feed->write(buffer+written,fileSize-written);
+ QTest::qWait(20);
+ counter++;
+ }
+ QTestEventLoop::instance().enterLoop(1);
+
+ QVERIFY(written == fileSize);
+ QVERIFY(audio->totalTime() == 692250);
+
+ audio->stop();
+ filename.close();
+ delete [] buffer;
+ delete audio;
+}
+
+QTEST_MAIN(tst_QAudioOutput)
+
+#include "tst_qaudiooutput.moc"
diff --git a/tests/auto/tests.xml b/tests/auto/tests.xml
index a5386b2..ccfc380 100644
--- a/tests/auto/tests.xml
+++ b/tests/auto/tests.xml
@@ -271,6 +271,10 @@
<Test name="qsocks5socketengine" location="tests/auto/qsocks5socketengine/tst_qsocks5socketengine" />
<Test name="qsortfilterproxymodel" location="tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel" />
<Test name="qsound" location="tests/auto/qsound/tst_qsound" />
+ <Test name="qaudiodeviceid" location="tests/auto/qaudiodeviceid/tst_qaudiodeviceid" />
+ <Test name="qaudioformat" location="tests/auto/qaudioformat/tst_qaudioformat" />
+ <Test name="qaudiooutput" location="tests/auto/qaudiooutput/tst_qaudiooutput" />
+ <Test name="qaudioinput" location="tests/auto/qaudioinput/tst_qaudioinput" />
<Test name="qsourcelocation" location="tests/auto/qsourcelocation/tst_qsourcelocation" />
<Test name="qspinbox" location="tests/auto/qspinbox/tst_qspinbox" />
<Test name="qsplitter" location="tests/auto/qsplitter/tst_qsplitter" />
@@ -676,6 +680,10 @@
<Test id="qsocks5socketengine" />
<Test id="qsortfilterproxymodel" />
<Test id="qsound" />
+ <Test id="qaudiodeviceid" />
+ <Test id="qaudioformat" />
+ <Test id="qaudiooutput" />
+ <Test id="qaudioinput" />
<Test id="qsourcelocation" />
<Test id="qspinbox" />
<Test id="qsplitter" />
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index c938919..f32e7dc 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -245,6 +245,7 @@ Configure::Configure( int& argc, char** argv )
dictionary[ "XMLPATTERNS" ] = "auto";
dictionary[ "PHONON" ] = "auto";
dictionary[ "PHONON_BACKEND" ] = "yes";
+ dictionary[ "MULTIMEDIA" ] = "yes";
dictionary[ "DIRECTSHOW" ] = "no";
dictionary[ "WEBKIT" ] = "auto";
dictionary[ "PLUGIN_MANIFESTS" ] = "yes";
@@ -843,6 +844,10 @@ void Configure::parseCmdLine()
dictionary[ "XMLPATTERNS" ] = "no";
} else if( configCmdLine.at(i) == "-xmlpatterns" ) {
dictionary[ "XMLPATTERNS" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-multimedia" ) {
+ dictionary[ "MULTIMEDIA" ] = "no";
+ } else if( configCmdLine.at(i) == "-multimedia" ) {
+ dictionary[ "MULTIMEDIA" ] = "yes";
} else if( configCmdLine.at(i) == "-no-phonon" ) {
dictionary[ "PHONON" ] = "no";
} else if( configCmdLine.at(i) == "-phonon" ) {
@@ -1425,6 +1430,7 @@ bool Configure::displayHelp()
"[-no-openssl] [-no-dbus] [-dbus] [-dbus-linked] [-platform <spec>]\n"
"[-qtnamespace <namespace>] [-qtlibinfix <infix>] [-no-phonon]\n"
"[-phonon] [-no-phonon-backend] [-phonon-backend]\n"
+ "[-no-multimedia] [-multimedia]\n"
"[-no-webkit] [-webkit]\n"
"[-no-scripttools] [-scripttools]\n"
"[-graphicssystem raster|opengl]\n\n", 0, 7);
@@ -1599,6 +1605,8 @@ bool Configure::displayHelp()
desc("PHONON", "yes", "-phonon", "Compile the Phonon module (Phonon is built if a decent C++ compiler is used.)");
desc("PHONON_BACKEND","no", "-no-phonon-backend","Do not compile the platform-specific Phonon backend-plugin");
desc("PHONON_BACKEND","yes","-phonon-backend", "Compile in the platform-specific Phonon backend-plugin");
+ desc("MULTIMEDIA", "no", "-no-multimedia", "Do not compile the multimedia module");
+ desc("MULTIMEDIA", "yes","-multimedia", "Compile in multimedia module");
desc("WEBKIT", "no", "-no-webkit", "Do not compile in the WebKit module");
desc("WEBKIT", "yes", "-webkit", "Compile in the WebKit module (WebKit is built if a decent C++ compiler is used.)");
desc("SCRIPTTOOLS", "no", "-no-scripttools", "Do not build the QtScriptTools module.");
@@ -1867,6 +1875,8 @@ bool Configure::checkAvailability(const QString &part)
if (!findFile("msdmo.lib")) cout << "msdmo.lib not found" << endl;
if (!findFile("d3d9.h")) cout << "d3d9.h not found" << endl;
}
+ } else if (part == "MULTIMEDIA") {
+ available = true;
} else if (part == "WEBKIT") {
available = (dictionary.value("QMAKESPEC") == "win32-msvc2005") || (dictionary.value("QMAKESPEC") == "win32-msvc2008") || (dictionary.value("QMAKESPEC") == "win32-g++");
} else if (part == "SCRIPTTOOLS") {
@@ -2302,6 +2312,9 @@ void Configure::generateOutputVars()
qtConfig += "phonon-backend";
}
+ if (dictionary["MULTIMEDIA"] == "yes")
+ qtConfig += "multimedia";
+
if (dictionary["WEBKIT"] == "yes")
qtConfig += "webkit";
@@ -2662,6 +2675,7 @@ void Configure::generateConfigfiles()
if(dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6";
if(dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT";
if(dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON";
+ if(dictionary["MULTIMEDIA"] == "no") qconfigList += "QT_NO_MULTIMEDIA";
if(dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS";
if(dictionary["SCRIPTTOOLS"] == "no") qconfigList += "QT_NO_SCRIPTTOOLS";
@@ -2920,6 +2934,7 @@ void Configure::displayConfig()
cout << "QtDBus support.............." << dictionary[ "DBUS" ] << endl;
cout << "QtXmlPatterns support......." << dictionary[ "XMLPATTERNS" ] << endl;
cout << "Phonon support.............." << dictionary[ "PHONON" ] << endl;
+ cout << "Multimedia support.........." << dictionary[ "MULTIMEDIA" ] << endl;
cout << "WebKit support.............." << dictionary[ "WEBKIT" ] << endl;
cout << "QtScriptTools support......." << dictionary[ "SCRIPTTOOLS" ] << endl;
cout << "Graphics System............." << dictionary[ "GRAPHICS_SYSTEM" ] << endl;