Initial copy of QtMultimediaKit.

Comes from original repo, with SHA1:
2c82d5611655e5967f5c5095af50c0991c4378b2
This commit is contained in:
Michael Goddard
2011-06-29 13:38:46 +10:00
commit 2a34e88c1e
1048 changed files with 206259 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
This directory contains the metadata for building and
packaging Qt Mobility on Harmattan.
HOW TO BUILD FOR HARMATTAN
==========================
(note: this is a brief overview and many aspects are uncovered)
From within Scratchbox, at the top level of the Mobility
source tree:
$ ln -s src/harmattaninstalls debian
$ dpkg-checkbuilddeps
$ fakeroot apt-get install (any missing dependencies mentioned above)
$ dpkg-buildpackage -rfakeroot

92
src/harmattaninstalls/api Normal file
View File

@@ -0,0 +1,92 @@
interface: QtContacts
type: library
scope: Nokia MeeGo
state: stable
libs-pkg: libqtm-contacts
dev-pkg: libqtm-common-dev libqtm-contacts-dev
interface: QtFeedback
type: library
scope: Nokia MeeGo
state: stable
libs-pkg: libqtm-feedback
dev-pkg: libqtm-common-dev libqtm-feedback-dev
interface: QtGallery
type: library
libs-pkg: libqtm-gallery
dev-pkg: libqtm-common-dev libqtm-gallery-dev
state: stable
scope: Nokia MeeGo
interface: QtLocation
type: library
libs-pkg: libqtm-location
dev-pkg: libqtm-common-dev libqtm-location-dev
state: stable
scope: Nokia MeeGo
interface: QtMessaging
type: library
libs-pkg: libqtm-messaging
dev-pkg: libqtm-common-dev libqtm-messaging-dev
state: stable
scope: Nokia MeeGo
interface: QtMultimediaKit
type: library
libs-pkg: libqtm-multimedia
dev-pkg: libqtm-common-dev libqtm-multimedia-dev
state: stable
scope: Nokia MeeGo
interface: QtOrganizer
type: library
libs-pkg: libqtm-organizer
dev-pkg: libqtm-common-dev libqtm-organizer-dev
state: stable
scope: Nokia MeeGo
interface: QtPublishSubscribe
type: library
libs-pkg: libqtm-publishsubscribe
dev-pkg: libqtm-common-dev libqtm-publishsubscribe-dev
state: stable
scope: Nokia MeeGo
interface: QtSensors
type: library
libs-pkg: libqtm-sensors
dev-pkg: libqtm-common-dev libqtm-sensors-dev
state: stable
scope: Nokia MeeGo
interface: QtServiceFramework
type: library
libs-pkg: libqtm-serviceframework
dev-pkg: libqtm-common-dev libqtm-serviceframework-dev
state: stable
scope: Nokia MeeGo
interface: QtSystemInfo
type: library
libs-pkg: libqtm-systeminfo
dev-pkg: libqtm-common-dev libqtm-systeminfo-dev
state: stable
scope: Nokia MeeGo
interface: QtVersit
type: library
libs-pkg: libqtm-versit
dev-pkg: libqtm-common-dev libqtm-versit-dev
state: stable
scope: Nokia MeeGo
interface: QtVersitOrganizer
type: library
libs-pkg: libqtm-versitorganizer
dev-pkg: libqtm-common-dev libqtm-versitorganizer-dev
state: stable
scope: Nokia MeeGo

View File

@@ -0,0 +1,178 @@
qt-mobility (1.2.0~git20110225) unstable; urgency=low
* Bumped up the version
-- Sunil Thaha <sunil.thaha@nokia.com> Fri, 25 Feb 2011 13:59:48 +1000
qt-mobility (1.2.0~git20110210) unstable; urgency=low
* Bump version to 1.2
* Fixes: NB#206728
-- Sunil Thaha <sunil.thaha@nokia.com> Wed, 10 Feb 2011 13:59:48 +1000
qt-mobility (1.1.1~git20110106) unstable; urgency=low
* Fixes: NB#212701 : added the commit 95e140e7 as a patch
-- Sunil Thaha <sunil.thaha@nokia.com> Thu, 06 Jan 2011 10:02:05 +1000
qt-mobility (1.1.1~git20101224) unstable; urgency=low
* Fixes: NB#212701 : added the commit feb61b9 as a patch
-- Sunil Thaha <sunil.thaha@nokia.com> Fri, 24 Dec 2010 17:30:55 +1000
qt-mobility (1.1.1~git20101217) unstable; urgency=low
* Updated the code base to releases/1.1.1
* Fixes: NB#212701 : added the commit feb61b9 as a patch
-- Sunil Thaha <sunil.thaha@nokia.com> Fri, 17 Dec 2010 17:30:55 +1000
qt-mobility (1.1.1~git20101207) unstable; urgency=low
* Fixes: NB#209489
-- Sunil Thaha <sunil.thaha@nokia.com> Tue, 07 Dec 2010 17:30:55 +1000
qt-mobility (1.1.1~git20101201) unstable; urgency=low
* Fixes: NB#189902
* Fixes: NB#189902
* Fixes: NB#199411
* Fixes: NB#198751
* Fixes: NB#201514
* Fixes: NB#203941
* Fixes: NB#208483
-- Qt Development Frameworks <qt-info@nokia.com> Wed, 01 Dec 2010 11:39:00 +1000
qt-mobility (1.1.1~git20101119-0maemo1) unstable; urgency=low
* Qt Organizer module
* Classes for calendar entries, todo tasks, journal entries and notes
* Qt Feedback module
* Classes for feedback (haptic/tactile feedback, general multimedia feedback)
* Initial release has limited multimedia support
* Qt Gallery module
* Classes for searching for documents, and viewing document meta-data.
* Qt Maps and Navigation API
Part of the Location module
* Class for routing, geocoding and reverse geocoding, and for displaying and interacting with maps.
* Qt Landmarks module
* Part of the Location module
* Classes for saving, retrieving and deleting landmarks
-- Qt Development Frameworks <qt-info@nokia.com> Fri, 19 Oct 2010 11:39:00 +1000
qt-mobility (1.1.0~git20101026-0maemo1) unstable; urgency=low
* New Modules:
* Feedback
*
* Modules Changed:
*
* Bug Fixes:
* JIRA#MOBILITY-1780
-- Qt Development Frameworks <qt-info@nokia.com> Tue, 26 Oct 2010 11:39:00 +1000
qt-mobility (1.1.0~git20101005-0maemo1) unstable; urgency=low
* Modules Integrated:
* QtContacts
* QtLocation
* QtMessaging
* QtMultimedia
* QtOrganizer
* QtPublishsubscribe
* QtSensors
* QtServiceframework
* QtSysteminfo
* QtVersit
* Bug Fixes
* NB#189907 : QtPositionProvider has too slow initiation
* NB#195969 : libqtm-organizer depends on libextendedkcal and it is deprecated
-- Qt Development Frameworks <qt-info@nokia.com> Tue, 05 Oct 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100922-0maemo1) unstable; urgency=low
* Updated base code 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Wed, 22 Sep 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100917-0maemo1) unstable; urgency=low
* Updated base code 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Fri, 17 Sep 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100916-0maemo2) unstable; urgency=low
* Updated base code 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Thu, 16 Sep 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100909-0maemo2) unstable; urgency=low
* Updated base code 1.1
* Fixes: NB#190298 - [METABUG] Upgrade Qt Mobility APIs to version 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Tue, 10 Sep 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100906-0maemo1) unstable; urgency=low
* Updated base code 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Tue, 06 Sep 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100831-0maemo1) unstable; urgency=low
* Updated base code 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Tue, 31 Aug 2010 11:39:00 +1000
qt-mobility (1.1.0~git20100817-0maemo1) unstable; urgency=low
* Updated base code 1.1
-- Qt Development Frameworks <qt-info@nokia.com> Fri, 20 Aug 2010 11:39:00 +1000
qt-mobility (1.0.2~git20100721-0maemo1) unstable; urgency=low
* Move component headers to their specific dev packages.
* Add missing pkgconfig files.
* Fixes: NB#180932 - Missing QtLocation.pc.
-- Qt Development Frameworks <qt-info@nokia.com> Wed, 21 Jul 2010 14:39:00 +1000
qt-mobility (1.0.2~git20100714-0maemo1) unstable; urgency=low
* Pull from upstream (qtmobility-releases/1.0.2)
* Fixes: 173824 - [METABUG] Integrate Qt Mobility APIs (contacts, versit, location)
* Fixes: 172247 - Headers missing from libqtm-serviceframework-dev package and installation issues.
-- Qt Development Frameworks <qt-info@nokia.com> Wed, 14 Jul 2010 17:00:00 +1000
qt-mobility (1.0.2~git20100623-0maemo1) unstable; urgency=low
* Pull from upstream (qtmobility/1.0)
-- Qt Development Frameworks <qt-info@nokia.com> Thu, 10 Jun 2010 13:50:00 +0200
qt-mobility (1.0.0~git20100429-0maemo1) unstable; urgency=low
* Pull from upstream
-- Qt Development Frameworks <qt-info@nokia.com> Fri, 30 Apr 2010 12:30:00 +1000
qt-mobility (1.0.0~git20100422-0maemo1) unstable; urgency=low
* Pull from upstream
-- Qt Development Frameworks <qt-info@nokia.com> Fri, 23 Apr 2010 15:10:00 +1000
qt-mobility (1.0.0~git20100304-0maemo1) unstable; urgency=low
* Initial release
-- Qt Development Frameworks <qt-info@nokia.com> Thu, 04 Mar 2010 15:52:12 +1000

View File

@@ -0,0 +1 @@
5

View File

@@ -0,0 +1,716 @@
Source: qt-mobility
Section: libs
Priority: extra
Maintainer: Qt Development Frameworks <qt-info@nokia.com>
Build-Depends: libqt4-dev (>= 4.7.0), cdbs, debhelper (>= 5), quilt, aegis-builder (>= 1.4),
libicd-network-wlan-dev, libqt4-opengl-dev (>= 4.7.0),
libconninet0-dev, libcontextsubscriber-dev, libbluetooth3-dev, libcontextprovider-dev,
libx11-dev, libsensord-dev (>= 0.6.4), libqt4-declarative-dev (>= 4.7.0),
libxrandr-dev, gstreamer0.10-plugins-bad-dev, icd2-dev, libasound2-dev,
libconnsettings0-dev, libgstreamer-plugins-base0.10-dev, libgstreamer0.10-dev, libtelepathy-qt4-1-dev,
libxrandr-dev, libxv-dev, osso-wlan-dev, x11proto-video-dev, libqmf-dev,
libmessagingif-dev, libcommhistory-dev, libblkid-dev, pulseaudio-dev, libimmvibe-dev[armel], libqtsparql-dev,
libmkcal-dev, libkcalcoren-dev, libresourceqt-dev, libqmsystem2-dev, libqtsparql-tracker-extensions-dev,
libudev-dev, libiphb-dev, meego-gstreamer0.10-interfaces-dev[armel], libbmeipc-dev, libiphb-dev
Standards-Version: 3.8.0
Package: libqtm-examples
Architecture: any
Section: devel
Depends: qt4-declarative-qmlviewer, ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility examples package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-dev
Architecture: any
Section: devel
Depends: ${shlibs:Depends}, ${misc:Depends}, libqtm-common-dev(= ${binary:Version}),
libqtm-contacts-dev(= ${binary:Version}), libqtm-feedback-dev(= ${binary:Version}),
libqtm-gallery-dev(= ${binary:Version}), libqtm-location-dev(= ${binary:Version}),
libqtm-messaging-dev(= ${binary:Version}), libqtm-multimedia-dev(= ${binary:Version}),
libqtm-organizer-dev(= ${binary:Version}), libqtm-publishsubscribe-dev(= ${binary:Version}),
libqtm-sensors-dev(= ${binary:Version}), libqtm-serviceframework-dev(= ${binary:Version}),
libqtm-systeminfo-dev(= ${binary:Version}), libqtm-versit-dev(= ${binary:Version}),
libqtm-versitorganizer-dev(= ${binary:Version}), libqtm-connectivity-dev(= ${binary:Version})
Description: Qt Mobility development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
This package contains development headers of each Mobility component
Package: libqtm-common-dev
Architecture: any
Section: devel
Depends: ${shlibs:Depends}, ${misc:Depends}, libqt4-dev, libqt4-declarative-dev
Description: Qt Mobility development package that contains the headers common to all modules
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
This package contains development headers common to each Mobility component
#Package: libqtm-doc
#Architecture: any
#Section: devel
#Depends: ${shlibs:Depends}, ${misc:Depends}
#Description: Qt Mobility documentation package
# Qt Mobility Project delivers a set of new APIs to Qt with features that are
# well known from the mobile device world, in particular phones. However,
# these APIs allow the developer to use these features with ease from one
# framework and apply them to phones, netbooks and non-mobile personal
# computers.
# .
# This package contains documentation for all Mobility components
Package: libqtm-multimedia
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Multimedia module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-multimedia-dbg
Architecture: any
Section: libdevel
Depends: libqtm-multimedia (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Multimedia debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-multimedia-dev
Architecture: any
Section: libs
Depends: libqtm-multimedia (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Multimedia development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-multimedia-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends},${misc:Depends}
XB-Maemo-CI-Packages: libqtm-multimedia
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Multimedia autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-feedback
Architecture: any
Section: libs
Depends: immvibed[armel], libqtm-multimedia (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Feedback module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-feedback-dbg
Architecture: any
Section: libdevel
Depends: libqtm-feedback (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Feedback debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-feedback-dev
Architecture: any
Section: libs
Depends: libqtm-feedback (= ${binary:Version}), libqtm-multimedia-dev (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Feedback development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-feedback-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${shlibs:Depends},${misc:Depends}
XB-Maemo-CI-Packages: libqtm-feedback
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Feedback autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-gallery
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Gallery Framework module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-gallery-dbg
Architecture: any
Section: libdevel
Depends: libqtm-gallery (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Gallery Framework debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-gallery-dev
Architecture: any
Section: libs
Depends: libqtm-gallery (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Gallery Framework development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-gallery-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${shlibs:Depends},${misc:Depends}
XB-Maemo-CI-Packages: libqtm-gallery
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Gallery autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-serviceframework
Architecture: any
Section: libs
Depends: libqt4-sql (>= 4.6.0), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Service Framework module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-serviceframework-dbg
Architecture: any
Section: libdevel
Depends: libqtm-serviceframework (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Service Framework debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-serviceframework-dev
Architecture: any
Section: libs
Depends: libqtm-serviceframework (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Service Framework development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-serviceframework-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends},${misc:Depends}
XB-Maemo-CI-Packages: libqtm-serviceframework
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Serviceframework autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-messaging
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Messaging module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-messaging-dbg
Architecture: any
Section: libdevel
Depends: libqtm-messaging (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Messaging debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-messaging-dev
Architecture: any
Section: libs
Depends: libqtm-messaging (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends},${misc:Depends}
Description: Qt Mobility Messaging development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-messaging-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends},${misc:Depends}
XB-Maemo-CI-Packages: libqtm-messaging
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Messaging autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-contacts
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Contacts module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-contacts-dbg
Architecture: any
Section: libdevel
Depends: libqtm-contacts (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Contacts debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-contacts-dev
Architecture: any
Section: libs
Depends: libqtm-contacts (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Contacts development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-contacts-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-contacts
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Contacts autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versit
Architecture: any
Section: libs
Depends: libqtm-contacts (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Versit module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versit-dbg
Architecture: any
Section: libdevel
Depends: libqtm-versit (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Versit debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versit-dev
Architecture: any
Section: libs
Depends: libqtm-versit (= ${binary:Version}), libqtm-contacts-dev (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Versit development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versit-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-versit
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Versit autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-organizer
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Organizer module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-organizer-dbg
Architecture: any
Section: libdevel
Depends: libqtm-organizer (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Organizer debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-organizer-dev
Architecture: any
Section: libs
Depends: libqtm-organizer (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Organizer development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-organizer-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-organizer
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Organizer autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versitorganizer
Architecture: any
Section: libs
Depends: libqtm-versit (= ${binary:Version}), libqtm-organizer (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Versit Organizer module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versitorganizer-dbg
Architecture: any
Section: libdevel
Depends: libqtm-versitorganizer (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Versit Organizer debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-versitorganizer-dev
Architecture: any
Section: libs
Depends: libqtm-versitorganizer (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), libqtm-versit-dev (= ${binary:Version}),
libqtm-organizer-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Versit Organizer development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
#Package: libqtm-versitorganizer-tests
#Architecture: any
#Section: libs
#Depends: ci-testing, ${shlibs:Depends}
#XB-Maemo-CI-Packages: libqtm-versitorganizer
#XB-Maemo-CI-Stage: staging
#Description: Qt Mobility Versit Organizer autotest package
# Qt Mobility Project delivers a set of new APIs to Qt with features that are
# well known from the mobile device world, in particular phones. However,
# these APIs allow the developer to use these features with ease from one
# framework and apply them to phones, netbooks and non-mobile personal
# computers.
Package: libqtm-publishsubscribe
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility PublishSubscribe module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-publishsubscribe-dbg
Architecture: any
Section: libdevel
Depends: libqtm-publishsubscribe (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility PublishSubscribe debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-publishsubscribe-dev
Architecture: any
Section: libs
Depends: libqtm-publishsubscribe (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility PublishSubscribe development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-publishsubscribe-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-publishsubscribe
XB-Maemo-CI-Stage: staging
Description: Qt Mobility PublishSubscribe autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-location
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}, libqtsparql-tracker, tracker (>= 0.9.35)
Recommends: positioningd
Description: Qt Mobility Location module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-location-dbg
Architecture: any
Section: libdevel
Depends: libqtm-location (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Location debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-location-dev
Architecture: any
Section: libs
Depends: libqtm-location (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Location development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-location-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-location
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Location autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-sensors
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Sensors module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-sensors-dbg
Architecture: any
Section: libdevel
Depends: libqtm-sensors (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Sensors debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-sensors-dev
Architecture: any
Section: libs
Depends: libqtm-sensors (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Sensors development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-sensors-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-sensors
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Sensors autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-systeminfo
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}, sysinfo-dbus
Description: Qt Mobility SystemInfo module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-systeminfo-dbg
Architecture: any
Section: libdevel
Depends: libqtm-systeminfo (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility SystemInfo debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-systeminfo-dev
Architecture: any
Section: libs
Depends: libqtm-systeminfo (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility SystemInfo development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-systeminfo-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-systeminfo
XB-Maemo-CI-Stage: staging
Description: Qt Mobility SystemInfo autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-connectivity
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Connectivity module
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-connectivity-dbg
Architecture: any
Section: libdevel
Depends: libqtm-connectivity (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Connectivity debugging symbols
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-connectivity-dev
Architecture: any
Section: libs
Depends: libqtm-connectivity (= ${binary:Version}), libqtm-common-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
Description: Qt Mobility Connectivity development package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.
Package: libqtm-connectivity-tests
Architecture: any
Section: libs
Depends: ci-testing, ${shlibs:Depends}, ${misc:Depends}
XB-Maemo-CI-Packages: libqtm-connectivity
XB-Maemo-CI-Stage: staging
Description: Qt Mobility Connectivity autotest package
Qt Mobility Project delivers a set of new APIs to Qt with features that are
well known from the mobile device world, in particular phones. However,
these APIs allow the developer to use these features with ease from one
framework and apply them to phones, netbooks and non-mobile personal
computers.

View File

@@ -0,0 +1,2 @@
INSTALL.txt
LGPL_EXCEPTION.txt

View File

@@ -0,0 +1,13 @@
<aegis>
<request>
<credential name="GRP::metadata-users" />
<credential name="TrackerReadAccess" />
<credential name="TrackerWriteAccess" />
<for path="/usr/tests/qtm/tst_qcontactasync" />
<for path="/usr/tests/qtm/tst_qcontactmanagerdetails" />
<for path="/usr/tests/qtm/tst_qcontactmanager" />
<for path="/usr/tests/qtm/tst_qcontactmanagerfiltering" />
<for path="/usr/tests/qtm/tst_bm_contactsoverhead" />
<for path="/usr/tests/qtm/tst_bm_contacts" />
</request>
</aegis>

View File

@@ -0,0 +1 @@
usr/doc/html/* usr/share/qt4/QtMobility/doc/html

View File

@@ -0,0 +1,54 @@
<aegis>
<request>
<credential name="TrackerReadAccess" />
<for path="/usr/lib/qtmobility/examples/declarative-music-browser" />
<for path="/usr/lib/qtmobility/examples/documentproperties" />
<for path="/usr/lib/qtmobility/examples/mediabrowser" />
</request>
<request>
<credential name="TrackerReadAccess" />
<credential name="TrackerWriteAccess" />
<credential name="GRP::metadata-users"/>
<for path="/usr/lib/qtmobility/examples/samplephonebook" />
<for path="/usr/lib/qtmobility/demos/qmlcontacts" />
</request>
<request>
<credential name="Location" />
<credential name="TrackerReadAccess" />
<credential name="TrackerWriteAccess" />
<for path="/usr/lib/qtmobility/examples/landmarkbrowser" />
<for path="/usr/lib/qtmobility/examples/qml_landmarkmap" />
<for path="/usr/lib/qtmobility/examples/qml_location_flickr" />
<for path="/usr/lib/qtmobility/examples/qml_mapviewer" />
<for path="/usr/lib/qtmobility/examples/flickrdemo" />
<for path="/usr/lib/qtmobility/demos/lightmaps_with_location" />
<for path="/usr/lib/qtmobility/demos/weatherinfo_with_location" />
</request>
<request>
<credential name="Cellular" />
<credential name="TrackerReadAccess" />
<for path="/usr/lib/qtmobility/demos/serviceactions" />
<for path="/usr/lib/qtmobility/examples/writemessage" />
<for path="/usr/lib/qtmobility/examples/querymessages" />
<for path="/usr/lib/qtmobility/examples/keepintouch" />
<for path="/usr/lib/qtmobility/examples/qml_messages" />
</request>
<request>
<credential name="Cellular" />
<credential name="Location" />
<credential name="TrackerReadAccess" />
<credential name="TrackerWriteAccess" />
<for path="/usr/lib/qtmobility/examples/mapsdemo" />
</request>
<request>
<credential name="mce::TKLockControl" />
<for path="/usr/lib/qtmobility/examples/qsysinfo" />
</request>
<request>
<credential name="GRP::video" />
<credential name="GRP::pulse-access" />
<for path="/usr/lib/qtmobility/demos/player" />
<for path="/usr/lib/qtmobility/examples/camera" />
<for path="/usr/lib/qtmobility/examples/qml_camera" />
</request>
</aegis>

View File

@@ -0,0 +1,100 @@
usr/lib/qt4/plugins/serviceframework/libserviceframework_bluetoothtransferplugin.so
usr/lib/qt4/plugins/serviceframework/libserviceframework_filemanagerplugin.so
usr/lib/qt4/plugins/serviceframework/libserviceframework_landlinedialerservice.so
usr/lib/qt4/plugins/serviceframework/libserviceframework_notesmanagerplugin.so
usr/lib/qt4/plugins/serviceframework/libserviceframework_voipdialerservice.so
usr/lib/qtmobility/demos/lightmaps_with_location
usr/lib/qtmobility/demos/nmealog.txt
usr/lib/qtmobility/demos/player
usr/lib/qtmobility/demos/qmlcontacts
usr/lib/qtmobility/demos/serviceactions
usr/lib/qtmobility/demos/smallsensors
usr/lib/qtmobility/demos/weatherinfo_with_location
usr/lib/qtmobility/examples/accel
usr/lib/qtmobility/examples/annotatedurl
usr/lib/qtmobility/examples/arrowkeys
usr/lib/qtmobility/examples/audiodevices
usr/lib/qtmobility/examples/audioinput
usr/lib/qtmobility/examples/audiooutput
usr/lib/qtmobility/examples/audiorecorder
usr/lib/qtmobility/examples/battery-publisher
usr/lib/qtmobility/examples/battery-subscriber/battery-subscriber.qml
usr/lib/qtmobility/examples/battery-subscriber/content/bubble.png
usr/lib/qtmobility/examples/btchat
usr/lib/qtmobility/examples/btfiletransfer
usr/lib/qtmobility/examples/btscanner
usr/lib/qtmobility/examples/bttennis
usr/lib/qtmobility/examples/calendardemo
usr/lib/qtmobility/examples/camera
usr/lib/qtmobility/examples/cubehouse
usr/lib/qtmobility/examples/declarative-music-browser
usr/lib/qtmobility/examples/dialer_service
usr/lib/qtmobility/examples/documentproperties
usr/lib/qtmobility/examples/flickrdemo
usr/lib/qtmobility/examples/grueapp
usr/lib/qtmobility/examples/hapticsplayer
usr/lib/qtmobility/examples/hapticsquare
usr/lib/qtmobility/examples/keepintouch
usr/lib/qtmobility/examples/landmarkbrowser
usr/lib/qtmobility/examples/logfilepositionsource
usr/lib/qtmobility/examples/mapsdemo
usr/lib/qtmobility/examples/mediabrowser
usr/lib/qtmobility/examples/metadata
usr/lib/qtmobility/examples/metadata2
usr/lib/qtmobility/examples/moreplaces.lmx
usr/lib/qtmobility/examples/mylm.lmx
usr/lib/qtmobility/examples/ndefeditor
usr/lib/qtmobility/examples/nmealog.txt
usr/lib/qtmobility/examples/orientation
usr/lib/qtmobility/examples/places.gpx
usr/lib/qtmobility/examples/publish-subscribe
usr/lib/qtmobility/examples/qml_battery
usr/lib/qtmobility/examples/qml_battery2
usr/lib/qtmobility/examples/qml_camera
usr/lib/qtmobility/examples/qml_device
usr/lib/qtmobility/examples/qmldialer
usr/lib/qtmobility/examples/qml_landmarkmap
usr/lib/qtmobility/examples/qml_location_flickr
usr/lib/qtmobility/examples/qml_mapviewer
usr/lib/qtmobility/examples/qml_networkinfo
usr/lib/qtmobility/examples/qmlnotes
usr/lib/qtmobility/examples/qmlorganizer
usr/lib/qtmobility/examples/qml_poster
usr/lib/qtmobility/examples/qml_scanner
usr/lib/qtmobility/examples/qml_storageinfo
usr/lib/qtmobility/examples/qml_tennis
usr/lib/qtmobility/examples/qsysinfo
usr/lib/qtmobility/examples/qsystemalignedtimer
usr/lib/qtmobility/examples/querymessages
usr/lib/qtmobility/examples/radio
usr/lib/qtmobility/examples/samplephonebook
usr/lib/qtmobility/examples/sensor_explorer
usr/lib/qtmobility/examples/servicebrowser
usr/lib/qtmobility/examples/sfwecho_client
usr/lib/qtmobility/examples/sfwecho_service
usr/lib/qtmobility/examples/sfw-notes
usr/lib/qtmobility/examples/show_acceleration
usr/lib/qtmobility/examples/show_als
usr/lib/qtmobility/examples/show_compass
usr/lib/qtmobility/examples/show_gyroscope
usr/lib/qtmobility/examples/show_light
usr/lib/qtmobility/examples/show_magneticflux
usr/lib/qtmobility/examples/show_orientation
usr/lib/qtmobility/examples/show_proximity
usr/lib/qtmobility/examples/show_reflectance
usr/lib/qtmobility/examples/show_rotation
usr/lib/qtmobility/examples/show_tap
usr/lib/qtmobility/examples/simplelog.txt
usr/lib/qtmobility/examples/slideshow
usr/lib/qtmobility/examples/todo
usr/lib/qtmobility/examples/videographicsitem
usr/lib/qtmobility/examples/videowidget
usr/lib/qtmobility/examples/writemessage
usr/lib/qtmobility/examples/xmldata/bluetoothtransferservice.xml
usr/lib/qtmobility/examples/xmldata/filemanagerservice.xml
usr/lib/qtmobility/examples/xmldata/landlinedialerservice.xml
usr/lib/qtmobility/examples/xmldata/notesmanagerservice.xml
usr/lib/qtmobility/examples/xmldata/remotedialerservice.xml
usr/lib/qtmobility/examples/xmldata/sfwechoservice.xml
usr/lib/qtmobility/examples/xmldata/voipdialerservice.xml
usr/lib/qtmobility/examples/qml_messages

View File

@@ -0,0 +1,145 @@
usr/include/qt4/QtMultimediaKit/QAbstractAudioDeviceInfo
usr/include/qt4/QtMultimediaKit/QAbstractAudioInput
usr/include/qt4/QtMultimediaKit/QAbstractAudioOutput
usr/include/qt4/QtMultimediaKit/QAbstractVideoBuffer
usr/include/qt4/QtMultimediaKit/QAbstractVideoSurface
usr/include/qt4/QtMultimediaKit/QAudio
usr/include/qt4/QtMultimediaKit/QAudioCaptureSource
usr/include/qt4/QtMultimediaKit/QAudioDeviceInfo
usr/include/qt4/QtMultimediaKit/QAudioEncoderControl
usr/include/qt4/QtMultimediaKit/QAudioEncoderSettings
usr/include/qt4/QtMultimediaKit/QAudioEndpointSelector
usr/include/qt4/QtMultimediaKit/QAudioFormat
usr/include/qt4/QtMultimediaKit/QAudioInput
usr/include/qt4/QtMultimediaKit/QAudioOutput
usr/include/qt4/QtMultimediaKit/QAudioSystemPlugin
usr/include/qt4/QtMultimediaKit/QCamera
usr/include/qt4/QtMultimediaKit/QCameraControl
usr/include/qt4/QtMultimediaKit/QCameraExposure
usr/include/qt4/QtMultimediaKit/QCameraExposureControl
usr/include/qt4/QtMultimediaKit/QCameraFlashControl
usr/include/qt4/QtMultimediaKit/QCameraFocus
usr/include/qt4/QtMultimediaKit/QCameraFocusControl
usr/include/qt4/QtMultimediaKit/QCameraFocusZone
usr/include/qt4/QtMultimediaKit/QCameraImageCapture
usr/include/qt4/QtMultimediaKit/QCameraImageCaptureControl
usr/include/qt4/QtMultimediaKit/QCameraCaptureBufferFormatControl
usr/include/qt4/QtMultimediaKit/QCameraCaptureDestinationControl
usr/include/qt4/QtMultimediaKit/QCameraImageProcessing
usr/include/qt4/QtMultimediaKit/QCameraImageProcessingControl
usr/include/qt4/QtMultimediaKit/QCameraLocksControl
usr/include/qt4/QtMultimediaKit/QCameraViewfinder
usr/include/qt4/QtMultimediaKit/QGraphicsVideoItem
usr/include/qt4/QtMultimediaKit/QImageEncoderControl
usr/include/qt4/QtMultimediaKit/QImageEncoderSettings
usr/include/qt4/QtMultimediaKit/QLocalMediaPlaylistProvider
usr/include/qt4/QtMultimediaKit/QMediaBindableInterface
usr/include/qt4/QtMultimediaKit/QMediaContainerControl
usr/include/qt4/QtMultimediaKit/QMediaContent
usr/include/qt4/QtMultimediaKit/QMediaControl
usr/include/qt4/QtMultimediaKit/QMediaImageViewer
usr/include/qt4/QtMultimediaKit/QMediaNetworkAccessControl
usr/include/qt4/QtMultimediaKit/QMediaObject
usr/include/qt4/QtMultimediaKit/QMediaPlayer
usr/include/qt4/QtMultimediaKit/QMediaPlayerControl
usr/include/qt4/QtMultimediaKit/QMediaPlaylist
usr/include/qt4/QtMultimediaKit/QMediaPlaylistControl
usr/include/qt4/QtMultimediaKit/QMediaPlaylistIOPlugin
usr/include/qt4/QtMultimediaKit/QMediaPlaylistNavigator
usr/include/qt4/QtMultimediaKit/QMediaPlaylistProvider
usr/include/qt4/QtMultimediaKit/QMediaPlaylistReader
usr/include/qt4/QtMultimediaKit/QMediaPlaylistSourceControl
usr/include/qt4/QtMultimediaKit/QMediaPlaylistWriter
usr/include/qt4/QtMultimediaKit/QMediaRecorder
usr/include/qt4/QtMultimediaKit/QMediaRecorderControl
usr/include/qt4/QtMultimediaKit/QMediaResource
usr/include/qt4/QtMultimediaKit/QMediaService
usr/include/qt4/QtMultimediaKit/QMediaServiceProvider
usr/include/qt4/QtMultimediaKit/QMediaServiceProviderHint
usr/include/qt4/QtMultimediaKit/QMediaServiceProviderPlugin
usr/include/qt4/QtMultimediaKit/QMediaStreamsControl
usr/include/qt4/QtMultimediaKit/QMediaTimeInterval
usr/include/qt4/QtMultimediaKit/QMediaTimeRange
usr/include/qt4/QtMultimediaKit/QMetaDataReaderControl
usr/include/qt4/QtMultimediaKit/QMetaDataWriterControl
usr/include/qt4/QtMultimediaKit/QRadioTuner
usr/include/qt4/QtMultimediaKit/QRadioTunerControl
usr/include/qt4/QtMultimediaKit/QVideoDeviceControl
usr/include/qt4/QtMultimediaKit/QVideoEncoderControl
usr/include/qt4/QtMultimediaKit/QVideoEncoderSettings
usr/include/qt4/QtMultimediaKit/QVideoFrame
usr/include/qt4/QtMultimediaKit/QVideoRendererControl
usr/include/qt4/QtMultimediaKit/QVideoSurfaceFormat
usr/include/qt4/QtMultimediaKit/QVideoWidget
usr/include/qt4/QtMultimediaKit/QVideoWidgetControl
usr/include/qt4/QtMultimediaKit/QVideoWindowControl
usr/include/qt4/QtMultimediaKit/qabstractvideobuffer.h
usr/include/qt4/QtMultimediaKit/qabstractvideosurface.h
usr/include/qt4/QtMultimediaKit/qaudio.h
usr/include/qt4/QtMultimediaKit/qaudiocapturesource.h
usr/include/qt4/QtMultimediaKit/qaudiodeviceinfo.h
usr/include/qt4/QtMultimediaKit/qaudioencodercontrol.h
usr/include/qt4/QtMultimediaKit/qaudioendpointselector.h
usr/include/qt4/QtMultimediaKit/qaudioformat.h
usr/include/qt4/QtMultimediaKit/qaudioinput.h
usr/include/qt4/QtMultimediaKit/qaudiooutput.h
usr/include/qt4/QtMultimediaKit/qaudiosystem.h
usr/include/qt4/QtMultimediaKit/qaudiosystemplugin.h
usr/include/qt4/QtMultimediaKit/qcamera.h
usr/include/qt4/QtMultimediaKit/qcameracontrol.h
usr/include/qt4/QtMultimediaKit/qcameraexposure.h
usr/include/qt4/QtMultimediaKit/qcameraexposurecontrol.h
usr/include/qt4/QtMultimediaKit/qcameraflashcontrol.h
usr/include/qt4/QtMultimediaKit/qcamerafocus.h
usr/include/qt4/QtMultimediaKit/qcamerafocuscontrol.h
usr/include/qt4/QtMultimediaKit/qcameraimagecapture.h
usr/include/qt4/QtMultimediaKit/qcameraimagecapturecontrol.h
usr/include/qt4/QtMultimediaKit/qcameracapturedestinationcontrol.h
usr/include/qt4/QtMultimediaKit/qcameracapturebufferformatcontrol.h
usr/include/qt4/QtMultimediaKit/qcameraimageprocessing.h
usr/include/qt4/QtMultimediaKit/qcameraimageprocessingcontrol.h
usr/include/qt4/QtMultimediaKit/qcameralockscontrol.h
usr/include/qt4/QtMultimediaKit/qcameraviewfinder.h
usr/include/qt4/QtMultimediaKit/qgraphicsvideoitem.h
usr/include/qt4/QtMultimediaKit/qimageencodercontrol.h
usr/include/qt4/QtMultimediaKit/qlocalmediaplaylistprovider.h
usr/include/qt4/QtMultimediaKit/qmediabindableinterface.h
usr/include/qt4/QtMultimediaKit/qmediacontainercontrol.h
usr/include/qt4/QtMultimediaKit/qmediacontent.h
usr/include/qt4/QtMultimediaKit/qmediacontrol.h
usr/include/qt4/QtMultimediaKit/qmediaencodersettings.h
usr/include/qt4/QtMultimediaKit/qmediaenumdebug.h
usr/include/qt4/QtMultimediaKit/qmediaimageviewer.h
usr/include/qt4/QtMultimediaKit/qmedianetworkaccesscontrol.h
usr/include/qt4/QtMultimediaKit/qmediaobject.h
usr/include/qt4/QtMultimediaKit/qmediaplayer.h
usr/include/qt4/QtMultimediaKit/qmediaplayercontrol.h
usr/include/qt4/QtMultimediaKit/qmediaplaylist.h
usr/include/qt4/QtMultimediaKit/qmediaplaylistcontrol.h
usr/include/qt4/QtMultimediaKit/qmediaplaylistioplugin.h
usr/include/qt4/QtMultimediaKit/qmediaplaylistnavigator.h
usr/include/qt4/QtMultimediaKit/qmediaplaylistprovider.h
usr/include/qt4/QtMultimediaKit/qmediaplaylistsourcecontrol.h
usr/include/qt4/QtMultimediaKit/qmediarecorder.h
usr/include/qt4/QtMultimediaKit/qmediarecordercontrol.h
usr/include/qt4/QtMultimediaKit/qmediaresource.h
usr/include/qt4/QtMultimediaKit/qmediaservice.h
usr/include/qt4/QtMultimediaKit/qmediaserviceprovider.h
usr/include/qt4/QtMultimediaKit/qmediaserviceproviderplugin.h
usr/include/qt4/QtMultimediaKit/qmediastreamscontrol.h
usr/include/qt4/QtMultimediaKit/qmediatimerange.h
usr/include/qt4/QtMultimediaKit/qmetadatareadercontrol.h
usr/include/qt4/QtMultimediaKit/qmetadatawritercontrol.h
usr/include/qt4/QtMultimediaKit/qradiotuner.h
usr/include/qt4/QtMultimediaKit/qradiotunercontrol.h
usr/include/qt4/QtMultimediaKit/qtmedianamespace.h
usr/include/qt4/QtMultimediaKit/qvideodevicecontrol.h
usr/include/qt4/QtMultimediaKit/qvideoencodercontrol.h
usr/include/qt4/QtMultimediaKit/qvideoframe.h
usr/include/qt4/QtMultimediaKit/qvideorenderercontrol.h
usr/include/qt4/QtMultimediaKit/qvideosurfaceformat.h
usr/include/qt4/QtMultimediaKit/qvideowidget.h
usr/include/qt4/QtMultimediaKit/qvideowidgetcontrol.h
usr/include/qt4/QtMultimediaKit/qvideowindowcontrol.h
usr/lib/libQtMultimediaKit.so
usr/lib/pkgconfig/QtMultimediaKit.pc

View File

@@ -0,0 +1,32 @@
usr/tests/qtm/tst_qmediaresource
usr/tests/qtm/tst_qmediatimerange
usr/tests/qtm/tst_qaudiooutput
usr/tests/qtm/tst_qabstractvideosurface
usr/tests/qtm/tst_qmediaimageviewer
usr/tests/qtm/tst_qcamera
usr/tests/qtm/tst_qmediaplayerbackend
usr/tests/qtm/tst_qvideoframe
usr/tests/qtm/tst_qabstractvideobuffer
usr/tests/qtm/tst_qdeclarativevideo
usr/tests/qtm/tst_qmediapluginloader
usr/tests/qtm/tst_qmediaplaylist
usr/tests/qtm/tst_qaudiocapturesource
usr/tests/qtm/tst_qmediarecorder
usr/tests/qtm/tst_qmediaserviceprovider
usr/tests/qtm/tst_qvideowidget
usr/tests/qtm/tst_qaudioinput
usr/tests/qtm/tst_qmediacontent
usr/tests/qtm/tst_qmediaplayer
usr/tests/qtm/tst_qpaintervideosurface
usr/tests/qtm/tst_qmediaplaylistnavigator
usr/tests/qtm/tst_qradiotuner
usr/tests/qtm/tst_qaudioformat
usr/tests/qtm/tst_qmediaservice
usr/tests/qtm/tst_qaudiodeviceinfo
usr/tests/qtm/tst_qsoundeffect
usr/tests/qtm/tst_qvideosurfaceformat
usr/tests/qtm/tst_qgraphicsvideoitem
usr/tests/qtm/tst_qdeclarativeaudio
usr/tests/qtm/tst_qmediaobject
usr/tests/qtm/tst_qcamerabackend
usr/share/libqtm-multimedia-tests/tests.xml

View File

@@ -0,0 +1,8 @@
usr/lib/libQtMultimediaKit.so.1.2.0
usr/lib/libQtMultimediaKit.so.1.2
usr/lib/libQtMultimediaKit.so.1
usr/lib/qt4/imports/QtMultimediaKit/libdeclarative_multimedia.so
usr/lib/qt4/imports/QtMultimediaKit/qmldir
usr/lib/qt4/plugins/audio/libqtmedia_pulse.so
usr/lib/qt4/plugins/mediaservice/libqgstengine.so
usr/lib/qt4/plugins/playlistformats/libqtmultimediakit_m3u.so

View File

@@ -0,0 +1,10 @@
<aegis>
<request>
<credential name="mce::TKLockControl" />
<for path="/usr/tests/qtm/tst_qsystemscreensaver" />
</request>
<request>
<credential name="mce::DeviceModeControl" />
<for path="/usr/tests/qtm/tst_qsystemnetworkinfo" />
</request>
</aegis>

View File

110
src/harmattaninstalls/rules Executable file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/make -f
#export DH_VERBOSE=1
# set MOBILITY_ENABLE_STATIC_CONFIG to 0 to disable using staticconfig in configure
MOBILITY_ENABLE_STATIC_CONFIG=1
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/rules/utils.mk
include /usr/share/cdbs/1/rules/patchsys-quilt.mk
include /usr/share/cdbs/1/class/autotools.mk
# Find out how many parallel threads to run
TMP_BUILD_OPTS = $(subst $(comma),$(space),$(DEB_BUILD_OPTIONS))
ifneq (,$(filter parallel=%,$(TMP_BUILD_OPTS)))
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(TMP_BUILD_OPTS)))
PARALLEL_MAKEFLAGS += -j$(NUMJOBS)
endif
DEB_MAKE_INVOKE := $(MAKE) $(PARALLEL_MAKEFLAGS)
DEB_MAKE_INSTALL_TARGET := INSTALL_ROOT=$(DEB_DESTDIR) install
DEB_DH_INSTALL_SOURCEDIR := debian/tmp
# DEB_DH_INSTALL_ARGS ensures that the build breaks if a file installed
# to DEB_DH_INSTALL_SOURCEDIR is not listed in any of the libqtm*.install files
# except the *.prl files (-X.prl)
DEB_DH_INSTALL_ARGS := --fail-missing -X.prl
# bearer location contacts multimedia publishsubscribe versit messaging systeminfo serviceframework sensors gallery organizer feedback connectivity
QTM_MODULES += connectivity
QTM_MODULES += contacts
QTM_MODULES += feedback
QTM_MODULES += gallery
QTM_MODULES += location
QTM_MODULES += messaging
QTM_MODULES += multimedia
QTM_MODULES += organizer
QTM_MODULES += publishsubscribe
QTM_MODULES += sensors
QTM_MODULES += serviceframework
QTM_MODULES += systeminfo
QTM_MODULES += versit
# Add here any variable or target overrides you need.
# Arguments to configure
DEB_CONFIGURE_NORMAL_ARGS := -maemo6 -prefix /usr -headerdir /usr/include/qt4 \
-plugindir /usr/lib/qt4/plugins -modules "$(QTM_MODULES)" \
-examples -examplesdir /usr/lib/qtmobility/examples \
-demos -demosdir /usr/lib/qtmobility/demos \
-silent -release -tests
# enable static config if set
ifeq ($(MOBILITY_ENABLE_STATIC_CONFIG),1)
TARGET_BUILD=x86
ifeq ($(DEB_HOST_ARCH),arm)
TARGET_BUILD=arm
endif
ifeq ($(DEB_HOST_ARCH),armel)
TARGET_BUILD=arm
endif
DEB_CONFIGURE_EXTRA_FLAGS := -staticconfig harmattan_$(TARGET_BUILD)
endif
common-install-arch:: install-autotests
#List of auto tests
QTM_MAEMO_TESTDIR := debian/tests
QTM_AUTOTESTS_SIMPLE := debian/libqtm-connectivity-tests.install \
debian/libqtm-contacts-tests.install \
debian/libqtm-feedback-tests.install \
debian/libqtm-gallery-tests.install \
debian/libqtm-location-tests.install \
debian/libqtm-messaging-tests.install \
debian/libqtm-multimedia-tests.install \
debian/libqtm-organizer-tests.install \
debian/libqtm-publishsubscribe-tests.install \
debian/libqtm-sensors-tests.install \
debian/libqtm-serviceframework-tests.install \
debian/libqtm-systeminfo-tests.install \
debian/libqtm-versit-tests.install
export QTM_TEST_INSTALL_FILE=$(CURDIR)/debian/pkg.install
#installation
install-autotests:
$(DEB_MAKE_INVOKE) -C tests INSTALL_ROOT=$(DEB_DESTDIR) installtests
$(QTM_MAEMO_TESTDIR)/install_tests -d debian -t $(QTM_MAEMO_TESTDIR) \
-i $(DEB_DESTDIR) -c -xml $(QTM_AUTOTESTS_SIMPLE)
PACKAGE_TARGETS := $(foreach pkg,$(DEB_ALL_PACKAGES),binary/$(pkg))
$(PACKAGE_TARGETS)::
[ ! -f debian/$(notdir $@).aegis ] || aegis-deb-add -control debian/$(notdir $@)/DEBIAN/control .. debian/$(notdir $@).aegis=_aegis
clean::
find \( -false \
-o -type f -name mobility*.prf \
\) -delete
rm -rf include build lib patches
# Delete the config tests and
rm -f \
config.tests/maemo-icd-network-wlan/maemo-icd-network-wlan \
config.tests/maemo-icd/maemo-icd \
config.tests/sensord/sensord \
config.tests/gstreamer-photography/gstreamer-photography \
config.tests/immersion/immersion \
config.tests/maemo6-landmarks/maemo6-landmarks \
config.tests/pulseaudio/pulseaudio

View File

@@ -0,0 +1,201 @@
#!/bin/sh
#############################################################################
##
## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
## All rights reserved.
## Contact: Nokia Corporation (qt-info@nokia.com)
##
## This file is the build configuration utility of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:LGPL$
## GNU Lesser General Public License Usage
## This file may be used under the terms of the GNU Lesser General Public
## License version 2.1 as published by the Free Software Foundation and
## appearing in the file LICENSE.LGPL included in the packaging of this
## file. Please review the following information to ensure the GNU Lesser
## General Public License version 2.1 requirements will be met:
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## In addition, as a special exception, Nokia gives you certain additional
## rights. These rights are described in the Nokia Qt LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU General
## Public License version 3.0 as published by the Free Software Foundation
## and appearing in the file LICENSE.GPL included in the packaging of this
## file. Please review the following information to ensure the GNU General
## Public License version 3.0 requirements will be met:
## http://www.gnu.org/copyleft/gpl.html.
##
## Other Usage
## Alternatively, this file may be used in accordance with the terms and
## conditions contained in a signed written agreement between you and Nokia.
##
##
##
##
##
## $QT_END_LICENSE$
##
#############################################################################
set -e
#-------------------------------------------------------------------------------
#Design assumptions:
## The name of the test application binary is tst_<subdir_where_test_is_located>
## The name of the project file passed to the scrpt is <package name>.<ext>
## The extension string is not relevant. Typical values: .pri, .pro, .conf
#-------------------------------------------------------------------------------
xmlInstallDir="usr/share"
testSuiteHeader="testsuite_header.txt"
testSuiteFooter="testsuite_footer.txt"
testSetTemplate="testset.txt"
#-------------------------------------------------------------------------------
#Parameters: $1 the project file where the tests are defined
#-------------------------------------------------------------------------------
install_tests()
{
#derive the package name from the file name
extension=".$(echo $1 | awk -F"." '{print $NF}')"
packageName=$(basename "$1" "$extension")
installFile="$packageDir/${packageName}.install"
mkdir -p $installDir/$xmlInstallDir/$packageName
xmlFile="$installDir/$xmlInstallDir/$packageName/tests.xml"
begin_test_suite $xmlFile
# only run applications, not test data or plugins (which will have a '.' in the name)
grep -v -F . "$installFile" | while read testApp; do
add_test_set "$testApp" "$xmlFile"
done
end_test_suite $xmlFile
}
#-------------------------------------------------------------------------------
#Parameters: $1 the xml output file'
#-------------------------------------------------------------------------------
begin_test_suite()
{
optstr="/<suite/s;name=\"[^\"]*\";name=\"$packageName\";g"
template="$templateDir/$testSuiteHeader"
runsed $optstr $template > "$1"
}
#Parameters: $1 the xml output file
end_test_suite()
{
cat "$templateDir/$testSuiteFooter" >> "$1"
}
#-------------------------------------------------------------------------------
#Parameters: $1 the name of the test application
#Parameters: $2 the xml output file
#-------------------------------------------------------------------------------
add_test_set()
{
templateSetFile="$templateDir/$testSetTemplate"
testSuiteName=$(basename $1)
insignificantTest="false"
# *.insignificant_test files indicate that the test should be marked as insignificant - run but not counted
if [ -e "$installDir/$1.insignificant_test" ]; then
insignificantTest="true"
rm "$installDir/$1.insignificant_test"
fi
# *.manual_test files indicate that the test is not to be run in CITA
if [ ! -e "$installDir/$1.manual_test" ]; then
add_set_name "$testSuiteName" "$templateSetFile" |add_description "$testSuiteName" |add_case_name "$testSuiteName" |add_insignificant_test "$insignificantTest" | add_step "$1" >> "$2"
else
rm "$installDir/$1.manual_test"
fi
}
add_set_name()
{
optstr="/<set/s;name=\"[^\"]*\";name=\"${packageName}_$1\";g"
runsed "$optstr" "$2"
}
add_case_name()
{
optstr="/<case/s;name=\"[^\"]*\";name=\"$1\";g"
runsed "$optstr" "$2"
}
add_description()
{
optstr="s;<description>.*</description>;<description>${packageName}:$1</description>;g"
runsed "$optstr" "$2"
}
add_step()
{
if [ -n "$testCliOptions" ]; then
optstr="s;<step>.*</step>;<step>/$1 $testCliOptions</step>;g"
else
optstr="s;<step>.*</step>;<step>/$1</step>;g"
fi
runsed "$optstr" "$2"
}
add_insignificant_test()
{
optstr="s;insignificant=\"[^\"]*\";insignificant=\"$1\";g"
runsed "$optstr" "$2"
}
runsed()
{
sedopt=$(echo $1)
cmd='sed -e "$sedopt" $2'
eval $cmd
}
#======= main =========
programName="$0"
usage="Usage: `basename $programName` -t <template_dir> -d <debian_dir> \
-i <dir_where_tests_will_be_installed> <project_files>"
if [ $# -le 0 ]; then
echo "$usage" 1>&2
exit 1
fi
while [ $# -gt 0 ]; do
case "$1" in
-t) templateDir=$(cd "$2"; pwd)
shift
;;
-d) packageDir=$(cd "$2"; pwd)
shift
;;
-i) installDir=$(cd "$2"; pwd)
shift
;;
-c) testCliOptions="$2"
shift
;;
*) projFileList="$projFileList $1";;
esac
shift
done
if [ -z "$templateDir" ]|| [ -z "$packageDir" ] || [ -z "$installDir" ]; then
echo "$usage" 1>&2
exit 1
fi
for projFile in $projFileList; do
install_tests $projFile
done

View File

@@ -0,0 +1,11 @@
<set feature="qtmobility" level="Component" name="##Package-name_test_name##" type="Functional">
<description>##Package-name:test_name##</description>
<case level="Component" name="##tst_foo##" type="Functional" insignificant="false">
<description>##Package-name:test_name##</description>
<step>/usr/tests/qtm/tst_foo</step>
</case>
<environments>
<scratchbox>true</scratchbox>
<hardware>true</hardware>
</environments>
</set>

View File

@@ -0,0 +1,2 @@
</suite>
</testdefinition>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<testdefinition version="1.0">
<suite domain="Application framework" level="Component" name="##Add your name here##" type="Functional">
<description />

5
src/imports/imports.pro Normal file
View File

@@ -0,0 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += multimedia

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtDeclarative/qdeclarativeextensionplugin.h>
#include <QtDeclarative/qdeclarative.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
#include "private/qsoundeffect_p.h"
#include "qdeclarativevideo_p.h"
#include "qdeclarativeaudio_p.h"
#include "qdeclarativemediametadata_p.h"
#include "qdeclarativecamera_p.h"
#include "qdeclarativecamerapreviewprovider_p.h"
QML_DECLARE_TYPE(QSoundEffect)
QT_BEGIN_NAMESPACE
class QMultimediaDeclarativeModule : public QDeclarativeExtensionPlugin
{
Q_OBJECT
public:
virtual void registerTypes(const char *uri)
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtMultimediaKit"));
qmlRegisterType<QSoundEffect>(uri, 1, 1, "SoundEffect");
qmlRegisterType<QDeclarativeAudio>(uri, 1, 1, "Audio");
qmlRegisterType<QDeclarativeVideo>(uri, 1, 1, "Video");
qmlRegisterType<QDeclarativeCamera>(uri, 1, 1, "Camera");
qmlRegisterType<QDeclarativeMediaMetaData>();
}
void initializeEngine(QDeclarativeEngine *engine, const char *uri)
{
Q_UNUSED(uri);
engine->addImageProvider("camera", new QDeclarativeCameraPreviewProvider);
}
};
QT_END_NAMESPACE
#include "multimedia.moc"
Q_EXPORT_PLUGIN2(qmultimediadeclarativemodule, QT_PREPEND_NAMESPACE(QMultimediaDeclarativeModule));

View File

@@ -0,0 +1,41 @@
TARGET = declarative_multimedia
TARGETPATH = Qt/multimediakit
include(../qimportbase.pri)
QT += declarative network multimediakit-private
DESTDIR = $$QT.multimediakit.imports/$$TARGETPATH
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
HEADERS += \
qdeclarativeaudio_p.h \
qdeclarativemediabase_p.h \
qdeclarativemediametadata_p.h \
qdeclarativevideo_p.h \
qdeclarativecamera_p.h \
qdeclarativecamerapreviewprovider_p.h
SOURCES += \
multimedia.cpp \
qdeclarativeaudio.cpp \
qdeclarativemediabase.cpp \
qdeclarativevideo.cpp \
qdeclarativecamera.cpp \
qdeclarativecamerapreviewprovider.cpp
qmldir.files += $$PWD/qmldir
qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
INSTALLS += target qmldir
symbian {
# In Symbian, a library should enjoy _largest_ possible capability set.
TARGET.CAPABILITY = ALL -TCB
TARGET.UID3 = 0x20021313
TARGET.EPOCALLOWDLLDATA=1
# Specifies what files shall be deployed: the plugin itself and the qmldir file.
importFiles.sources = $$DESTDIR/declarative_multimedia$${QT_LIBINFIX}.dll qmldir
importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH
DEPLOYMENT = importFiles
}

View File

@@ -0,0 +1,698 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qdeclarativeaudio_p.h"
#include <qmediaplayercontrol.h>
QT_BEGIN_NAMESPACE
/*!
\qmlclass Audio QDeclarativeAudio
\brief The Audio element allows you to add audio playback to a scene.
\ingroup qml-multimedia
This element is part of the \bold{QtMultimediaKit 1.1} module.
\qml
import Qt 4.7
import QtMultimediaKit 1.1
Text {
text: "Click Me!";
font.pointSize: 24;
width: 150; height: 50;
Audio {
id: playMusic
source: "music.wav"
}
MouseArea {
id: playArea
anchors.fill: parent
onPressed: { playMusic.play() }
}
}
\endqml
\sa Video
*/
/*!
\internal
\class QDeclarativeAudio
\brief The QDeclarativeAudio class provides an audio item that you can add to a QDeclarativeView.
*/
void QDeclarativeAudio::_q_error(int errorCode, const QString &errorString)
{
m_error = QMediaPlayer::Error(errorCode);
m_errorString = errorString;
emit error(Error(errorCode), errorString);
emit errorChanged();
}
QDeclarativeAudio::QDeclarativeAudio(QObject *parent)
: QObject(parent)
{
}
QDeclarativeAudio::~QDeclarativeAudio()
{
shutdown();
}
/*!
\qmlmethod Audio::play()
Starts playback of the media.
Sets the \l playing property to true, and the \l paused property to false.
*/
void QDeclarativeAudio::play()
{
if (!m_complete)
return;
setPaused(false);
setPlaying(true);
}
/*!
\qmlmethod Audio::pause()
Pauses playback of the media.
Sets the \l playing and \l paused properties to true.
*/
void QDeclarativeAudio::pause()
{
if (!m_complete)
return;
setPaused(true);
setPlaying(true);
}
/*!
\qmlmethod Audio::stop()
Stops playback of the media.
Sets the \l playing and \l paused properties to false.
*/
void QDeclarativeAudio::stop()
{
if (!m_complete)
return;
setPlaying(false);
setPaused(false);
}
/*!
\qmlproperty url Audio::source
This property holds the source URL of the media.
*/
/*!
\qmlproperty url Audio::autoLoad
This property indicates if loading of media should begin immediately.
Defaults to true, if false media will not be loaded until playback is started.
*/
/*!
\qmlproperty bool Audio::playing
This property holds whether the media is playing.
Defaults to false, and can be set to true to start playback.
*/
/*!
\qmlproperty bool Audio::paused
This property holds whether the media is paused.
Defaults to false, and can be set to true to pause playback.
*/
/*!
\qmlsignal Audio::onStarted()
This handler is called when playback is started.
*/
/*!
\qmlsignal Audio::onResumed()
This handler is called when playback is resumed from the paused state.
*/
/*!
\qmlsignal Audio::onPaused()
This handler is called when playback is paused.
*/
/*!
\qmlsignal Audio::onStopped()
This handler is called when playback is stopped.
*/
/*!
\qmlproperty enumeration Audio::status
This property holds the status of media loading. It can be one of:
\list
\o NoMedia - no media has been set.
\o Loading - the media is currently being loaded.
\o Loaded - the media has been loaded.
\o Buffering - the media is buffering data.
\o Stalled - playback has been interrupted while the media is buffering data.
\o Buffered - the media has buffered data.
\o EndOfMedia - the media has played to the end.
\o InvalidMedia - the media cannot be played.
\o UnknownStatus - the status of the media is unknown.
\endlist
*/
QDeclarativeAudio::Status QDeclarativeAudio::status() const
{
return Status(m_status);
}
/*!
\qmlproperty int Audio::duration
This property holds the duration of the media in milliseconds.
If the media doesn't have a fixed duration (a live stream for example) this will be 0.
*/
/*!
\qmlproperty int Audio::position
This property holds the current playback position in milliseconds.
If the \l seekable property is true, this property can be set to seek to a new position.
*/
/*!
\qmlproperty real Audio::volume
This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
*/
/*!
\qmlproperty bool Audio::muted
This property holds whether the audio output is muted.
*/
/*!
\qmlproperty real Audio::bufferProgress
This property holds how much of the data buffer is currently filled, from 0.0 (empty) to 1.0
(full).
*/
/*!
\qmlproperty bool Audio::seekable
This property holds whether position of the audio can be changed.
If true; setting a \l position value will cause playback to seek to the new position.
*/
/*!
\qmlproperty real Audio::playbackRate
This property holds the rate at which audio is played at as a multiple of the normal rate.
*/
/*!
\qmlproperty enumeration Audio::error
This property holds the error state of the audio. It can be one of:
\list
\o NoError - there is no current error.
\o ResourceError - the audio cannot be played due to a problem allocating resources.
\o FormatError - the audio format is not supported.
\o NetworkError - the audio cannot be played due to network issues.
\o AccessDenied - the audio cannot be played due to insufficient permissions.
\o ServiceMissing - the audio cannot be played because the media service could not be
instantiated.
\endlist
*/
QDeclarativeAudio::Error QDeclarativeAudio::error() const
{
return Error(m_error);
}
void QDeclarativeAudio::classBegin()
{
setObject(this);
}
void QDeclarativeAudio::componentComplete()
{
QDeclarativeMediaBase::componentComplete();
}
/*!
\qmlproperty string Audio::errorString
This property holds a string describing the current error condition in more detail.
*/
/*!
\qmlsignal Audio::onError(error, errorString)
This handler is called when an \l {QMediaPlayer::Error}{error} has
occurred. The errorString parameter may contain more detailed
information about the error.
*/
/*!
\qmlproperty variant Audio::metaData.title
This property holds the tile of the media.
\sa {QtMultimediaKit::Title}
*/
/*!
\qmlproperty variant Audio::metaData.subTitle
This property holds the sub-title of the media.
\sa {QtMultimediaKit::SubTitle}
*/
/*!
\qmlproperty variant Audio::metaData.author
This property holds the author of the media.
\sa {QtMultimediaKit::Author}
*/
/*!
\qmlproperty variant Audio::metaData.comment
This property holds a user comment about the media.
\sa {QtMultimediaKit::Comment}
*/
/*!
\qmlproperty variant Audio::metaData.description
This property holds a description of the media.
\sa {QtMultimediaKit::Description}
*/
/*!
\qmlproperty variant Audio::metaData.category
This property holds the category of the media
\sa {QtMultimediaKit::Category}
*/
/*!
\qmlproperty variant Audio::metaData.genre
This property holds the genre of the media.
\sa {QtMultimediaKit::Genre}
*/
/*!
\qmlproperty variant Audio::metaData.year
This property holds the year of release of the media.
\sa {QtMultimediaKit::Year}
*/
/*!
\qmlproperty variant Audio::metaData.date
This property holds the date of the media.
\sa {QtMultimediaKit::Date}
*/
/*!
\qmlproperty variant Audio::metaData.userRating
This property holds a user rating of the media in the range of 0 to 100.
\sa {QtMultimediaKit::UserRating}
*/
/*!
\qmlproperty variant Audio::metaData.keywords
This property holds a list of keywords describing the media.
\sa {QtMultimediaKit::Keywords}
*/
/*!
\qmlproperty variant Audio::metaData.language
This property holds the language of the media, as an ISO 639-2 code.
\sa {QtMultimediaKit::Language}
*/
/*!
\qmlproperty variant Audio::metaData.publisher
This property holds the publisher of the media.
\sa {QtMultimediaKit::Publisher}
*/
/*!
\qmlproperty variant Audio::metaData.copyright
This property holds the media's copyright notice.
\sa {QtMultimediaKit::Copyright}
*/
/*!
\qmlproperty variant Audio::metaData.parentalRating
This property holds the parental rating of the media.
\sa {QtMultimediaKit::ParentalRating}
*/
/*!
\qmlproperty variant Audio::metaData.ratingOrganisation
This property holds the name of the rating organisation responsible for the
parental rating of the media.
\sa {QtMultimediaKit::RatingOrganisation}
*/
/*!
\qmlproperty variant Audio::metaData.size
This property property holds the size of the media in bytes.
\sa {QtMultimediaKit::Size}
*/
/*!
\qmlproperty variant Audio::metaData.mediaType
This property holds the type of the media.
\sa {QtMultimediaKit::MediaType}
*/
/*!
\qmlproperty variant Audio::metaData.audioBitRate
This property holds the bit rate of the media's audio stream ni bits per
second.
\sa {QtMultimediaKit::AudioBitRate}
*/
/*!
\qmlproperty variant Audio::metaData.audioCodec
This property holds the encoding of the media audio stream.
\sa {QtMultimediaKit::AudioCodec}
*/
/*!
\qmlproperty variant Audio::metaData.averageLevel
This property holds the average volume level of the media.
\sa {QtMultimediaKit::AverageLevel}
*/
/*!
\qmlproperty variant Audio::metaData.channelCount
This property holds the number of channels in the media's audio stream.
\sa {QtMultimediaKit::ChannelCount}
*/
/*!
\qmlproperty variant Audio::metaData.peakValue
This property holds the peak volume of media's audio stream.
\sa {QtMultimediaKit::PeakValue}
*/
/*!
\qmlproperty variant Audio::metaData.sampleRate
This property holds the sample rate of the media's audio stream in hertz.
\sa {QtMultimediaKit::SampleRate}
*/
/*!
\qmlproperty variant Audio::metaData.albumTitle
This property holds the title of the album the media belongs to.
\sa {QtMultimediaKit::AlbumTitle}
*/
/*!
\qmlproperty variant Audio::metaData.albumArtist
This property holds the name of the principal artist of the album the media
belongs to.
\sa {QtMultimediaKit::AlbumArtist}
*/
/*!
\qmlproperty variant Audio::metaData.contributingArtist
This property holds the names of artists contributing to the media.
\sa {QtMultimediaKit::ContributingArtist}
*/
/*!
\qmlproperty variant Audio::metaData.composer
This property holds the composer of the media.
\sa {QtMultimediaKit::Composer}
*/
/*!
\qmlproperty variant Audio::metaData.conductor
This property holds the conductor of the media.
\sa {QtMultimediaKit::Conductor}
*/
/*!
\qmlproperty variant Audio::metaData.lyrics
This property holds the lyrics to the media.
\sa {QtMultimediaKit::Lyrics}
*/
/*!
\qmlproperty variant Audio::metaData.mood
This property holds the mood of the media.
\sa {QtMultimediaKit::Mood}
*/
/*!
\qmlproperty variant Audio::metaData.trackNumber
This property holds the track number of the media.
\sa {QtMultimediaKit::TrackNumber}
*/
/*!
\qmlproperty variant Audio::metaData.trackCount
This property holds the number of track on the album containing the media.
\sa {QtMultimediaKit::TrackNumber}
*/
/*!
\qmlproperty variant Audio::metaData.coverArtUrlSmall
This property holds the URL of a small cover art image.
\sa {QtMultimediaKit::CoverArtUrlSmall}
*/
/*!
\qmlproperty variant Audio::metaData.coverArtUrlLarge
This property holds the URL of a large cover art image.
\sa {QtMultimediaKit::CoverArtUrlLarge}
*/
/*!
\qmlproperty variant Audio::metaData.resolution
This property holds the dimension of an image or video.
\sa {QtMultimediaKit::Resolution}
*/
/*!
\qmlproperty variant Audio::metaData.pixelAspectRatio
This property holds the pixel aspect ratio of an image or video.
\sa {QtMultimediaKit::PixelAspectRatio}
*/
/*!
\qmlproperty variant Audio::metaData.videoFrameRate
This property holds the frame rate of the media's video stream.
\sa {QtMultimediaKit::VideoFrameRate}
*/
/*!
\qmlproperty variant Audio::metaData.videoBitRate
This property holds the bit rate of the media's video stream in bits per
second.
\sa {QtMultimediaKit::VideoBitRate}
*/
/*!
\qmlproperty variant Audio::metaData.videoCodec
This property holds the encoding of the media's video stream.
\sa {QtMultimediaKit::VideoCodec}
*/
/*!
\qmlproperty variant Audio::metaData.posterUrl
This property holds the URL of a poster image.
\sa {QtMultimediaKit::PosterUrl}
*/
/*!
\qmlproperty variant Audio::metaData.chapterNumber
This property holds the chapter number of the media.
\sa {QtMultimediaKit::ChapterNumber}
*/
/*!
\qmlproperty variant Audio::metaData.director
This property holds the director of the media.
\sa {QtMultimediaKit::Director}
*/
/*!
\qmlproperty variant Audio::metaData.leadPerformer
This property holds the lead performer in the media.
\sa {QtMultimediaKit::LeadPerformer}
*/
/*!
\qmlproperty variant Audio::metaData.writer
This property holds the writer of the media.
\sa {QtMultimediaKit::Writer}
*/
QT_END_NAMESPACE
#include "moc_qdeclarativeaudio_p.cpp"

View File

@@ -0,0 +1,178 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDECLARATIVEAUDIO_P_H
#define QDECLARATIVEAUDIO_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qdeclarativemediabase_p.h"
#include <QtCore/qbasictimer.h>
#include <QtDeclarative/qdeclarativeitem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QTimerEvent;
class QDeclarativeAudio : public QObject, public QDeclarativeMediaBase, public QDeclarativeParserStatus
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
Q_PROPERTY(int position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
Q_PROPERTY(int bufferProgress READ bufferProgress NOTIFY bufferProgressChanged)
Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged)
Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
Q_PROPERTY(Error error READ error NOTIFY errorChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
Q_PROPERTY(QDeclarativeMediaMetaData *metaData READ metaData CONSTANT)
Q_ENUMS(Status)
Q_ENUMS(Error)
Q_ENUMS(Loop)
Q_INTERFACES(QDeclarativeParserStatus)
public:
enum Status
{
UnknownStatus = QMediaPlayer::UnknownMediaStatus,
NoMedia = QMediaPlayer::NoMedia,
Loading = QMediaPlayer::LoadingMedia,
Loaded = QMediaPlayer::LoadedMedia,
Stalled = QMediaPlayer::StalledMedia,
Buffering = QMediaPlayer::BufferingMedia,
Buffered = QMediaPlayer::BufferedMedia,
EndOfMedia = QMediaPlayer::EndOfMedia,
InvalidMedia = QMediaPlayer::InvalidMedia
};
enum Error
{
NoError = QMediaPlayer::NoError,
ResourceError = QMediaPlayer::ResourceError,
FormatError = QMediaPlayer::FormatError,
NetworkError = QMediaPlayer::NetworkError,
AccessDenied = QMediaPlayer::AccessDeniedError,
ServiceMissing = QMediaPlayer::ServiceMissingError
};
enum Loop
{
Infinite = QDeclarativeMediaBase::INFINITE
};
QDeclarativeAudio(QObject *parent = 0);
~QDeclarativeAudio();
Status status() const;
Error error() const;
void classBegin();
void componentComplete();
public Q_SLOTS:
void play();
void pause();
void stop();
Q_SIGNALS:
void sourceChanged();
void autoLoadChanged();
void playingChanged();
void pausedChanged();
void loopCountChanged();
void started();
void resumed();
void paused();
void stopped();
void statusChanged();
void durationChanged();
void positionChanged();
void volumeChanged();
void mutedChanged();
void bufferProgressChanged();
void seekableChanged();
void playbackRateChanged();
void errorChanged();
void error(QDeclarativeAudio::Error error, const QString &errorString);
private Q_SLOTS:
void _q_error(int, const QString &);
private:
Q_DISABLE_COPY(QDeclarativeAudio)
Q_PRIVATE_SLOT(mediaBase(), void _q_statusChanged())
inline QDeclarativeMediaBase *mediaBase() { return this; }
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativeAudio))
QT_END_HEADER
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,302 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDECLARATIVECAMERA_H
#define QDECLARATIVECAMERA_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qgraphicsvideoitem.h"
#include <QtCore/qbasictimer.h>
#include <QtDeclarative/qdeclarativeitem.h>
#include <QtCore/QTime>
#include <qcamera.h>
#include <qcameraimageprocessing.h>
#include <qcameraimagecapture.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QTimerEvent;
class QVideoSurfaceFormat;
class QDeclarativeCamera : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(State cameraState READ cameraState WRITE setCameraState NOTIFY cameraStateChanged)
Q_PROPERTY(LockStatus lockStatus READ lockStatus NOTIFY lockStatusChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
Q_PROPERTY(QString capturedImagePath READ capturedImagePath NOTIFY imageSaved)
Q_PROPERTY(int iso READ isoSensitivity WRITE setManualIsoSensitivity NOTIFY isoSensitivityChanged)
Q_PROPERTY(qreal shutterSpeed READ shutterSpeed NOTIFY shutterSpeedChanged)
Q_PROPERTY(qreal aperture READ aperture NOTIFY apertureChanged)
Q_PROPERTY(qreal exposureCompensation READ exposureCompensation WRITE setExposureCompensation NOTIFY exposureCompensationChanged)
Q_PROPERTY(ExposureMode exposureMode READ exposureMode WRITE setExposureMode NOTIFY exposureModeChanged)
Q_PROPERTY(int flashMode READ flashMode WRITE setFlashMode NOTIFY flashModeChanged)
Q_PROPERTY(WhiteBalanceMode whiteBalanceMode READ whiteBalanceMode WRITE setWhiteBalanceMode NOTIFY whiteBalanceModeChanged)
Q_PROPERTY(int manualWhiteBalance READ manualWhiteBalance WRITE setManualWhiteBalance NOTIFY manualWhiteBalanceChanged)
Q_PROPERTY(QSize captureResolution READ captureResolution WRITE setCaptureResolution NOTIFY captureResolutionChanged)
Q_PROPERTY(qreal opticalZoom READ opticalZoom WRITE setOpticalZoom NOTIFY opticalZoomChanged)
Q_PROPERTY(qreal maximumOpticalZoom READ maximumOpticalZoom NOTIFY maximumOpticalZoomChanged)
Q_PROPERTY(qreal digitalZoom READ digitalZoom WRITE setDigitalZoom NOTIFY digitalZoomChanged)
Q_PROPERTY(qreal maximumDigitalZoom READ maximumDigitalZoom NOTIFY maximumDigitalZoomChanged)
Q_ENUMS(State)
Q_ENUMS(LockStatus)
Q_ENUMS(Error)
Q_ENUMS(FlashMode)
Q_ENUMS(ExposureMode)
Q_ENUMS(WhiteBalanceMode)
public:
enum State
{
ActiveState = QCamera::ActiveState,
LoadedState = QCamera::LoadedState,
UnloadedState = QCamera::UnloadedState
};
enum LockStatus
{
Unlocked = QCamera::Unlocked,
Searching = QCamera::Searching,
Locked = QCamera::Locked
};
enum Error
{
NoError = QCamera::NoError,
CameraError = QCamera::CameraError,
InvalidRequestError = QCamera::InvalidRequestError,
ServiceMissingError = QCamera::ServiceMissingError,
NotSupportedFeatureError = QCamera::NotSupportedFeatureError
};
enum FlashMode {
FlashAuto = 0x1,
FlashOff = 0x2,
FlashOn = 0x4,
FlashRedEyeReduction = 0x8,
FlashFill = 0x10,
FlashTorch = 0x20,
FlashSlowSyncFrontCurtain = 0x40,
FlashSlowSyncRearCurtain = 0x80,
FlashManual = 0x100
};
enum ExposureMode {
ExposureAuto = 0,
ExposureManual = 1,
ExposurePortrait = 2,
ExposureNight = 3,
ExposureBacklight = 4,
ExposureSpotlight = 5,
ExposureSports = 6,
ExposureSnow = 7,
ExposureBeach = 8,
ExposureLargeAperture = 9,
ExposureSmallAperture = 10,
ExposureModeVendor = 1000
};
enum WhiteBalanceMode {
WhiteBalanceAuto = 0,
WhiteBalanceManual = 1,
WhiteBalanceSunlight = 2,
WhiteBalanceCloudy = 3,
WhiteBalanceShade = 4,
WhiteBalanceTungsten = 5,
WhiteBalanceFluorescent = 6,
WhiteBalanceIncandescent = 7,
WhiteBalanceFlash = 8,
WhiteBalanceSunset = 9,
WhiteBalanceVendor = 1000
};
QDeclarativeCamera(QDeclarativeItem *parent = 0);
~QDeclarativeCamera();
State cameraState() const;
Error error() const;
QString errorString() const;
LockStatus lockStatus() const;
QImage capturedImagePreview() const;
QString capturedImagePath() const;
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
int flashMode() const;
ExposureMode exposureMode() const;
qreal exposureCompensation() const;
int isoSensitivity() const;
qreal shutterSpeed() const;
qreal aperture() const;
WhiteBalanceMode whiteBalanceMode() const;
int manualWhiteBalance() const;
QSize captureResolution() const;
qreal maximumOpticalZoom() const;
qreal maximumDigitalZoom() const;
qreal opticalZoom() const;
qreal digitalZoom() const;
public Q_SLOTS:
void start();
void stop();
void setCameraState(State state);
void searchAndLock();
void unlock();
void captureImage();
void setFlashMode(int);
void setExposureMode(QDeclarativeCamera::ExposureMode);
void setExposureCompensation(qreal ev);
void setManualIsoSensitivity(int iso);
void setWhiteBalanceMode(QDeclarativeCamera::WhiteBalanceMode mode) const;
void setManualWhiteBalance(int colorTemp) const;
void setCaptureResolution(const QSize &size);
void setOpticalZoom(qreal);
void setDigitalZoom(qreal);
Q_SIGNALS:
void errorChanged();
void error(QDeclarativeCamera::Error error, const QString &errorString);
void cameraStateChanged(QDeclarativeCamera::State);
void lockStatusChanged();
void imageCaptured(const QString &preview);
void imageSaved(const QString &path);
void captureFailed(const QString &message);
void isoSensitivityChanged(int);
void apertureChanged(qreal);
void shutterSpeedChanged(qreal);
void exposureCompensationChanged(qreal);
void exposureModeChanged(QDeclarativeCamera::ExposureMode);
void flashModeChanged(int);
void whiteBalanceModeChanged(QDeclarativeCamera::WhiteBalanceMode) const;
void manualWhiteBalanceChanged(int) const;
void captureResolutionChanged(const QSize&);
void opticalZoomChanged(qreal);
void digitalZoomChanged(qreal);
void maximumOpticalZoomChanged(qreal);
void maximumDigitalZoomChanged(qreal);
protected:
void geometryChanged(const QRectF &geometry, const QRectF &);
void keyPressEvent(QKeyEvent * event);
void keyReleaseEvent(QKeyEvent * event);
private Q_SLOTS:
void _q_updateState(QCamera::State);
void _q_nativeSizeChanged(const QSizeF &size);
void _q_error(int, const QString &);
void _q_imageCaptured(int, const QImage&);
void _q_imageSaved(int, const QString&);
void _q_captureFailed(int, QCameraImageCapture::Error, const QString&);
void _q_updateFocusZones();
void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason);
void _q_updateImageSettings();
void _q_applyPendingState();
private:
Q_DISABLE_COPY(QDeclarativeCamera)
QCamera *m_camera;
QGraphicsVideoItem *m_viewfinderItem;
QCameraExposure *m_exposure;
QCameraFocus *m_focus;
QCameraImageCapture *m_capture;
QImage m_capturedImagePreview;
QString m_capturedImagePath;
QList <QGraphicsItem*> m_focusZones;
QTime m_focusFailedTime;
QImageEncoderSettings m_imageSettings;
bool m_imageSettingsChanged;
State m_pendingState;
bool m_isStateSet;
bool m_isValid;
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativeCamera))
QT_END_HEADER
#endif

View File

@@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qdeclarativecamerapreviewprovider_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
struct QDeclarativeCameraPreviewProviderPrivate
{
QString id;
QImage image;
QMutex mutex;
};
Q_GLOBAL_STATIC(QDeclarativeCameraPreviewProviderPrivate, qDeclarativeCameraPreviewProviderPrivate)
QDeclarativeCameraPreviewProvider::QDeclarativeCameraPreviewProvider()
: QDeclarativeImageProvider(QDeclarativeImageProvider::Image)
{
}
QDeclarativeCameraPreviewProvider::~QDeclarativeCameraPreviewProvider()
{
QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
QMutexLocker lock(&d->mutex);
d->id.clear();
d->image = QImage();
}
QImage QDeclarativeCameraPreviewProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize)
{
QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
QMutexLocker lock(&d->mutex);
if (d->id != id)
return QImage();
QImage res = d->image;
if (!requestedSize.isEmpty())
res = res.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
if (size)
*size = res.size();
return res;
}
void QDeclarativeCameraPreviewProvider::registerPreview(const QString &id, const QImage &preview)
{
//only the last preview is kept
QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate();
QMutexLocker lock(&d->mutex);
d->id = id;
d->image = preview;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDECLARATIVECAMERAPREVIEWPROVIDER_H
#define QDECLARATIVECAMERAPREVIEWPROVIDER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtDeclarative/qdeclarativeimageprovider.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QDeclarativeCameraPreviewProvider : public QDeclarativeImageProvider
{
public:
QDeclarativeCameraPreviewProvider();
~QDeclarativeCameraPreviewProvider();
virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize);
static void registerPreview(const QString &id, const QImage &preview);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,567 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qdeclarativemediabase_p.h"
#include <QtCore/qcoreevent.h>
#include <QtCore/qurl.h>
#include <QtDeclarative/qdeclarativeinfo.h>
#include <qmediaplayercontrol.h>
#include <qmediaservice.h>
#include <qmediaserviceprovider.h>
#include <qmetadatareadercontrol.h>
#include "qdeclarativemediametadata_p.h"
QT_BEGIN_NAMESPACE
class QDeclarativeMediaBaseObject : public QMediaObject
{
public:
QDeclarativeMediaBaseObject(QMediaService *service)
: QMediaObject(0, service)
{
}
};
class QDeclarativeMediaBasePlayerControl : public QMediaPlayerControl
{
public:
QDeclarativeMediaBasePlayerControl(QObject *parent)
: QMediaPlayerControl(parent)
{
}
QMediaPlayer::State state() const { return QMediaPlayer::StoppedState; }
QMediaPlayer::MediaStatus mediaStatus() const { return QMediaPlayer::NoMedia; }
qint64 duration() const { return 0; }
qint64 position() const { return 0; }
void setPosition(qint64) {}
int volume() const { return 0; }
void setVolume(int) {}
bool isMuted() const { return false; }
void setMuted(bool) {}
int bufferStatus() const { return 0; }
bool isAudioAvailable() const { return false; }
bool isVideoAvailable() const { return false; }
bool isSeekable() const { return false; }
QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); }
qreal playbackRate() const { return 1; }
void setPlaybackRate(qreal) {}
QMediaContent media() const { return QMediaContent(); }
const QIODevice *mediaStream() const { return 0; }
void setMedia(const QMediaContent &, QIODevice *) {}
void play() {}
void pause() {}
void stop() {}
};
class QDeclarativeMediaBaseMetaDataControl : public QMetaDataReaderControl
{
public:
QDeclarativeMediaBaseMetaDataControl(QObject *parent)
: QMetaDataReaderControl(parent)
{
}
bool isMetaDataAvailable() const { return false; }
QVariant metaData(QtMultimediaKit::MetaData) const { return QVariant(); }
QList<QtMultimediaKit::MetaData> availableMetaData() const {
return QList<QtMultimediaKit::MetaData>(); }
QVariant extendedMetaData(const QString &) const { return QVariant(); }
QStringList availableExtendedMetaData() const { return QStringList(); }
};
class QDeclarativeMediaBaseAnimation : public QObject
{
public:
QDeclarativeMediaBaseAnimation(QDeclarativeMediaBase *media)
: m_media(media)
{
}
void start() { if (!m_timer.isActive()) m_timer.start(500, this); }
void stop() { m_timer.stop(); }
protected:
void timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_timer.timerId()) {
event->accept();
if (m_media->m_playing && !m_media->m_paused)
emit m_media->positionChanged();
if (m_media->m_status == QMediaPlayer::BufferingMedia || QMediaPlayer::StalledMedia)
emit m_media->bufferProgressChanged();
} else {
QObject::timerEvent(event);
}
}
private:
QDeclarativeMediaBase *m_media;
QBasicTimer m_timer;
};
void QDeclarativeMediaBase::_q_statusChanged()
{
if (m_playerControl->mediaStatus() == QMediaPlayer::EndOfMedia && m_runningCount != 0) {
m_runningCount -= 1;
m_playerControl->play();
}
const QMediaPlayer::MediaStatus oldStatus = m_status;
const bool wasPlaying = m_playing;
const bool wasPaused = m_paused;
const QMediaPlayer::State state = m_playerControl->state();
m_status = m_playerControl->mediaStatus();
if (m_complete)
m_playing = state != QMediaPlayer::StoppedState;
if (state == QMediaPlayer::PausedState)
m_paused = true;
else if (state == QMediaPlayer::PlayingState)
m_paused = false;
if (m_status != oldStatus)
emit statusChanged();
switch (state) {
case QMediaPlayer::StoppedState:
if (wasPlaying) {
emit stopped();
if (!m_playing)
emit playingChanged();
}
break;
case QMediaPlayer::PausedState:
if (!wasPlaying) {
emit started();
if (m_playing)
emit playingChanged();
}
if ((!wasPaused || !wasPlaying) && m_paused)
emit paused();
if (!wasPaused && m_paused)
emit pausedChanged();
break;
case QMediaPlayer::PlayingState:
if (wasPaused && wasPlaying)
emit resumed();
else
emit started();
if (wasPaused && !m_paused)
emit pausedChanged();
if (!wasPlaying && m_playing)
emit playingChanged();
break;
}
// Check
if ((m_playing && !m_paused)
|| m_status == QMediaPlayer::BufferingMedia
|| m_status == QMediaPlayer::StalledMedia) {
m_animation->start();
}
else {
m_animation->stop();
}
}
QDeclarativeMediaBase::QDeclarativeMediaBase()
: m_paused(false)
, m_playing(false)
, m_autoLoad(true)
, m_loaded(false)
, m_muted(false)
, m_complete(false)
, m_loopCount(1)
, m_runningCount(0)
, m_position(0)
, m_vol(1.0)
, m_playbackRate(1.0)
, m_mediaService(0)
, m_playerControl(0)
, m_qmlObject(0)
, m_mediaObject(0)
, m_mediaProvider(0)
, m_metaDataControl(0)
, m_animation(0)
, m_status(QMediaPlayer::NoMedia)
, m_error(QMediaPlayer::ServiceMissingError)
{
}
QDeclarativeMediaBase::~QDeclarativeMediaBase()
{
}
void QDeclarativeMediaBase::shutdown()
{
delete m_mediaObject;
m_metaData.reset();
if (m_mediaProvider)
m_mediaProvider->releaseService(m_mediaService);
delete m_animation;
}
void QDeclarativeMediaBase::setObject(QObject *object)
{
m_qmlObject = object;
if ((m_mediaProvider = QMediaServiceProvider::defaultServiceProvider()) != 0) {
if ((m_mediaService = m_mediaProvider->requestService(Q_MEDIASERVICE_MEDIAPLAYER)) != 0) {
m_playerControl = qobject_cast<QMediaPlayerControl *>(
m_mediaService->requestControl(QMediaPlayerControl_iid));
m_metaDataControl = qobject_cast<QMetaDataReaderControl *>(
m_mediaService->requestControl(QMetaDataReaderControl_iid));
m_mediaObject = new QDeclarativeMediaBaseObject(m_mediaService);
}
}
if (m_playerControl) {
QObject::connect(m_playerControl, SIGNAL(stateChanged(QMediaPlayer::State)),
object, SLOT(_q_statusChanged()));
QObject::connect(m_playerControl, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
object, SLOT(_q_statusChanged()));
QObject::connect(m_playerControl, SIGNAL(mediaChanged(QMediaContent)),
object, SIGNAL(sourceChanged()));
QObject::connect(m_playerControl, SIGNAL(durationChanged(qint64)),
object, SIGNAL(durationChanged()));
QObject::connect(m_playerControl, SIGNAL(positionChanged(qint64)),
object, SIGNAL(positionChanged()));
QObject::connect(m_playerControl, SIGNAL(volumeChanged(int)),
object, SIGNAL(volumeChanged()));
QObject::connect(m_playerControl, SIGNAL(mutedChanged(bool)),
object, SIGNAL(mutedChanged()));
QObject::connect(m_playerControl, SIGNAL(bufferStatusChanged(int)),
object, SIGNAL(bufferProgressChanged()));
QObject::connect(m_playerControl, SIGNAL(seekableChanged(bool)),
object, SIGNAL(seekableChanged()));
QObject::connect(m_playerControl, SIGNAL(playbackRateChanged(qreal)),
object, SIGNAL(playbackRateChanged()));
QObject::connect(m_playerControl, SIGNAL(error(int,QString)),
object, SLOT(_q_error(int,QString)));
m_animation = new QDeclarativeMediaBaseAnimation(this);
m_error = QMediaPlayer::NoError;
} else {
m_playerControl = new QDeclarativeMediaBasePlayerControl(object);
}
if (!m_metaDataControl)
m_metaDataControl = new QDeclarativeMediaBaseMetaDataControl(object);
m_metaData.reset(new QDeclarativeMediaMetaData(m_metaDataControl));
QObject::connect(m_metaDataControl, SIGNAL(metaDataChanged()),
m_metaData.data(), SIGNAL(metaDataChanged()));
}
void QDeclarativeMediaBase::componentComplete()
{
m_playerControl->setVolume(m_vol * 100);
m_playerControl->setMuted(m_muted);
m_playerControl->setPlaybackRate(m_playbackRate);
if (!m_source.isEmpty() && (m_autoLoad || m_playing)) // Override autoLoad if playing set
m_playerControl->setMedia(m_source, 0);
m_complete = true;
if (m_playing) {
if (m_position > 0)
m_playerControl->setPosition(m_position);
if (m_source.isEmpty()) {
m_playing = false;
emit playingChanged();
} else if (m_paused) {
m_playerControl->pause();
} else {
m_playerControl->play();
}
}
}
// Properties
QUrl QDeclarativeMediaBase::source() const
{
return m_source;
}
void QDeclarativeMediaBase::setSource(const QUrl &url)
{
if (url == m_source)
return;
m_source = url;
m_loaded = false;
if (m_complete && (m_autoLoad || url.isEmpty())) {
if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) {
m_error = QMediaPlayer::NoError;
m_errorString = QString();
emit errorChanged();
}
m_playerControl->setMedia(m_source, 0);
m_loaded = true;
}
else
emit sourceChanged();
}
bool QDeclarativeMediaBase::isAutoLoad() const
{
return m_autoLoad;
}
void QDeclarativeMediaBase::setAutoLoad(bool autoLoad)
{
if (m_autoLoad == autoLoad)
return;
m_autoLoad = autoLoad;
emit autoLoadChanged();
}
int QDeclarativeMediaBase::loopCount() const
{
return m_loopCount;
}
void QDeclarativeMediaBase::setLoopCount(int loopCount)
{
if (loopCount == 0)
loopCount = 1;
else if (loopCount < -1)
loopCount = -1;
if (m_loopCount == loopCount) {
return;
}
m_loopCount = loopCount;
emit loopCountChanged();
}
bool QDeclarativeMediaBase::isPlaying() const
{
return m_playing;
}
void QDeclarativeMediaBase::setPlaying(bool playing)
{
if (playing == m_playing)
return;
if (m_complete) {
if (playing) {
if (!m_autoLoad && !m_loaded) {
m_playerControl->setMedia(m_source, 0);
m_playerControl->setPosition(m_position);
m_loaded = true;
}
m_runningCount = m_loopCount - 1;
if (!m_paused)
m_playerControl->play();
else
m_playerControl->pause();
} else {
m_playerControl->stop();
}
} else {
m_playing = playing;
emit playingChanged();
}
}
bool QDeclarativeMediaBase::isPaused() const
{
return m_paused;
}
void QDeclarativeMediaBase::setPaused(bool paused)
{
if (m_paused == paused)
return;
if (m_complete && m_playing) {
if (!m_autoLoad && !m_loaded) {
m_playerControl->setMedia(m_source, 0);
m_playerControl->setPosition(m_position);
m_loaded = true;
}
if (!paused)
m_playerControl->play();
else
m_playerControl->pause();
} else {
m_paused = paused;
emit pausedChanged();
}
}
int QDeclarativeMediaBase::duration() const
{
return !m_complete ? 0 : m_playerControl->duration();
}
int QDeclarativeMediaBase::position() const
{
return !m_complete ? m_position : m_playerControl->position();
}
void QDeclarativeMediaBase::setPosition(int position)
{
if (this->position() == position)
return;
m_position = position;
if (m_complete)
m_playerControl->setPosition(m_position);
else
emit positionChanged();
}
qreal QDeclarativeMediaBase::volume() const
{
return !m_complete ? m_vol : qreal(m_playerControl->volume()) / 100;
}
void QDeclarativeMediaBase::setVolume(qreal volume)
{
if (volume < 0 || volume > 1) {
qmlInfo(m_qmlObject) << m_qmlObject->tr("volume should be between 0.0 and 1.0");
return;
}
if (m_vol == volume)
return;
m_vol = volume;
if (m_complete)
m_playerControl->setVolume(qRound(volume * 100));
else
emit volumeChanged();
}
bool QDeclarativeMediaBase::isMuted() const
{
return !m_complete ? m_muted : m_playerControl->isMuted();
}
void QDeclarativeMediaBase::setMuted(bool muted)
{
if (m_muted == muted)
return;
m_muted = muted;
if (m_complete)
m_playerControl->setMuted(muted);
else
emit mutedChanged();
}
qreal QDeclarativeMediaBase::bufferProgress() const
{
return !m_complete ? 0 : qreal(m_playerControl->bufferStatus()) / 100;
}
bool QDeclarativeMediaBase::isSeekable() const
{
return !m_complete ? false : m_playerControl->isSeekable();
}
qreal QDeclarativeMediaBase::playbackRate() const
{
return m_playbackRate;
}
void QDeclarativeMediaBase::setPlaybackRate(qreal rate)
{
if (m_playbackRate == rate)
return;
m_playbackRate = rate;
if (m_complete)
m_playerControl->setPlaybackRate(m_playbackRate);
else
emit playbackRateChanged();
}
QString QDeclarativeMediaBase::errorString() const
{
return m_errorString;
}
QDeclarativeMediaMetaData *QDeclarativeMediaBase::metaData() const
{
return m_metaData.data();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,187 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDECLARATIVEMEDIABASE_P_H
#define QDECLARATIVEMEDIABASE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qbasictimer.h>
#include <qmediaplayer.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QMediaPlayerControl;
class QMediaService;
class QMediaServiceProvider;
class QMetaDataReaderControl;
class QDeclarativeMediaBaseAnimation;
class QDeclarativeMediaMetaData;
class QDeclarativeMediaBase
{
public:
enum Loop {
INFINITE = -1
};
QDeclarativeMediaBase();
virtual ~QDeclarativeMediaBase();
QUrl source() const;
void setSource(const QUrl &url);
bool isAutoLoad() const;
void setAutoLoad(bool autoLoad);
int loopCount() const;
void setLoopCount(int loopCount);
bool isPlaying() const;
void setPlaying(bool playing);
bool isPaused() const;
void setPaused(bool paused);
int duration() const;
int position() const;
void setPosition(int position);
qreal volume() const;
void setVolume(qreal volume);
bool isMuted() const;
void setMuted(bool muted);
qreal bufferProgress() const;
bool isSeekable() const;
qreal playbackRate() const;
void setPlaybackRate(qreal rate);
QString errorString() const;
QDeclarativeMediaMetaData *metaData() const;
void _q_statusChanged();
void _q_metaDataChanged();
void componentComplete();
protected:
void shutdown();
void setObject(QObject *object);
virtual void sourceChanged() = 0;
virtual void autoLoadChanged() = 0;
virtual void playingChanged() = 0;
virtual void pausedChanged() = 0;
virtual void loopCountChanged() = 0;
virtual void started() = 0;
virtual void resumed() = 0;
virtual void paused() = 0;
virtual void stopped() = 0;
virtual void statusChanged() = 0;
virtual void durationChanged() = 0;
virtual void positionChanged() = 0;
virtual void volumeChanged() = 0;
virtual void mutedChanged() = 0;
virtual void bufferProgressChanged() = 0;
virtual void seekableChanged() = 0;
virtual void playbackRateChanged() = 0;
virtual void errorChanged() = 0;
bool m_paused;
bool m_playing;
bool m_autoLoad;
bool m_loaded;
bool m_muted;
bool m_complete;
int m_loopCount;
int m_runningCount;
int m_position;
qreal m_vol;
qreal m_playbackRate;
QMediaService *m_mediaService;
QMediaPlayerControl *m_playerControl;
QObject *m_qmlObject;
QMediaObject *m_mediaObject;
QMediaServiceProvider *m_mediaProvider;
QMetaDataReaderControl *m_metaDataControl;
QDeclarativeMediaBaseAnimation *m_animation;
QScopedPointer<QDeclarativeMediaMetaData> m_metaData;
QMediaPlayer::MediaStatus m_status;
QMediaPlayer::Error m_error;
QString m_errorString;
QUrl m_source;
friend class QDeclarativeMediaBaseAnimation;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,185 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDECLARATIVEMEDIAMETADATA_P_H
#define QDECLARATIVEMEDIAMETADATA_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <qmetadatareadercontrol.h>
#include <qdeclarative.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QDeclarativeMediaMetaData : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant title READ title NOTIFY metaDataChanged)
Q_PROPERTY(QVariant subTitle READ subTitle NOTIFY metaDataChanged)
Q_PROPERTY(QVariant author READ author NOTIFY metaDataChanged)
Q_PROPERTY(QVariant comment READ comment NOTIFY metaDataChanged)
Q_PROPERTY(QVariant description READ description NOTIFY metaDataChanged)
Q_PROPERTY(QVariant category READ category NOTIFY metaDataChanged)
Q_PROPERTY(QVariant genre READ genre NOTIFY metaDataChanged)
Q_PROPERTY(QVariant year READ year NOTIFY metaDataChanged)
Q_PROPERTY(QVariant date READ date NOTIFY metaDataChanged)
Q_PROPERTY(QVariant userRating READ userRating NOTIFY metaDataChanged)
Q_PROPERTY(QVariant keywords READ keywords NOTIFY metaDataChanged)
Q_PROPERTY(QVariant language READ language NOTIFY metaDataChanged)
Q_PROPERTY(QVariant publisher READ publisher NOTIFY metaDataChanged)
Q_PROPERTY(QVariant copyright READ copyright NOTIFY metaDataChanged)
Q_PROPERTY(QVariant parentalRating READ parentalRating NOTIFY metaDataChanged)
Q_PROPERTY(QVariant ratingOrganisation READ ratingOrganisation NOTIFY metaDataChanged)
Q_PROPERTY(QVariant size READ size NOTIFY metaDataChanged)
Q_PROPERTY(QVariant mediaType READ mediaType NOTIFY metaDataChanged)
Q_PROPERTY(QVariant duration READ duration NOTIFY metaDataChanged)
Q_PROPERTY(QVariant audioBitRate READ audioBitRate NOTIFY metaDataChanged)
Q_PROPERTY(QVariant audioCodec READ audioCodec NOTIFY metaDataChanged)
Q_PROPERTY(QVariant averageLevel READ averageLevel NOTIFY metaDataChanged)
Q_PROPERTY(QVariant channelCount READ channelCount NOTIFY metaDataChanged)
Q_PROPERTY(QVariant peakValue READ peakValue NOTIFY metaDataChanged)
Q_PROPERTY(QVariant sampleRate READ sampleRate NOTIFY metaDataChanged)
Q_PROPERTY(QVariant albumTitle READ albumTitle NOTIFY metaDataChanged)
Q_PROPERTY(QVariant albumArtist READ albumArtist NOTIFY metaDataChanged)
Q_PROPERTY(QVariant contributingArtist READ contributingArtist NOTIFY metaDataChanged)
Q_PROPERTY(QVariant composer READ composer NOTIFY metaDataChanged)
Q_PROPERTY(QVariant conductor READ conductor NOTIFY metaDataChanged)
Q_PROPERTY(QVariant lyrics READ lyrics NOTIFY metaDataChanged)
Q_PROPERTY(QVariant mood READ mood NOTIFY metaDataChanged)
Q_PROPERTY(QVariant trackNumber READ trackNumber NOTIFY metaDataChanged)
Q_PROPERTY(QVariant trackCount READ trackCount NOTIFY metaDataChanged)
Q_PROPERTY(QVariant coverArtUrlSmall READ coverArtUrlSmall NOTIFY metaDataChanged)
Q_PROPERTY(QVariant coverArtUrlLarge READ coverArtUrlLarge NOTIFY metaDataChanged)
Q_PROPERTY(QVariant resolution READ resolution NOTIFY metaDataChanged)
Q_PROPERTY(QVariant pixelAspectRatio READ pixelAspectRatio NOTIFY metaDataChanged)
Q_PROPERTY(QVariant videoFrameRate READ videoFrameRate NOTIFY metaDataChanged)
Q_PROPERTY(QVariant videoBitRate READ videoBitRate NOTIFY metaDataChanged)
Q_PROPERTY(QVariant videoCodec READ videoCodec NOTIFY metaDataChanged)
Q_PROPERTY(QVariant posterUrl READ posterUrl NOTIFY metaDataChanged)
Q_PROPERTY(QVariant chapterNumber READ chapterNumber NOTIFY metaDataChanged)
Q_PROPERTY(QVariant director READ director NOTIFY metaDataChanged)
Q_PROPERTY(QVariant leadPerformer READ leadPerformer NOTIFY metaDataChanged)
Q_PROPERTY(QVariant writer READ writer NOTIFY metaDataChanged)
public:
QDeclarativeMediaMetaData(QMetaDataReaderControl *control, QObject *parent = 0)
: QObject(parent)
, m_control(control)
{
}
QVariant title() const { return m_control->metaData(QtMultimediaKit::Title); }
QVariant subTitle() const { return m_control->metaData(QtMultimediaKit::SubTitle); }
QVariant author() const { return m_control->metaData(QtMultimediaKit::Author); }
QVariant comment() const { return m_control->metaData(QtMultimediaKit::Comment); }
QVariant description() const { return m_control->metaData(QtMultimediaKit::Description); }
QVariant category() const { return m_control->metaData(QtMultimediaKit::Category); }
QVariant genre() const { return m_control->metaData(QtMultimediaKit::Genre); }
QVariant year() const { return m_control->metaData(QtMultimediaKit::Year); }
QVariant date() const { return m_control->metaData(QtMultimediaKit::Date); }
QVariant userRating() const { return m_control->metaData(QtMultimediaKit::UserRating); }
QVariant keywords() const { return m_control->metaData(QtMultimediaKit::Keywords); }
QVariant language() const { return m_control->metaData(QtMultimediaKit::Language); }
QVariant publisher() const { return m_control->metaData(QtMultimediaKit::Publisher); }
QVariant copyright() const { return m_control->metaData(QtMultimediaKit::Copyright); }
QVariant parentalRating() const { return m_control->metaData(QtMultimediaKit::ParentalRating); }
QVariant ratingOrganisation() const {
return m_control->metaData(QtMultimediaKit::RatingOrganisation); }
QVariant size() const { return m_control->metaData(QtMultimediaKit::Size); }
QVariant mediaType() const { return m_control->metaData(QtMultimediaKit::MediaType); }
QVariant duration() const { return m_control->metaData(QtMultimediaKit::Duration); }
QVariant audioBitRate() const { return m_control->metaData(QtMultimediaKit::AudioBitRate); }
QVariant audioCodec() const { return m_control->metaData(QtMultimediaKit::AudioCodec); }
QVariant averageLevel() const { return m_control->metaData(QtMultimediaKit::AverageLevel); }
QVariant channelCount() const { return m_control->metaData(QtMultimediaKit::ChannelCount); }
QVariant peakValue() const { return m_control->metaData(QtMultimediaKit::PeakValue); }
QVariant sampleRate() const { return m_control->metaData(QtMultimediaKit::SampleRate); }
QVariant albumTitle() const { return m_control->metaData(QtMultimediaKit::AlbumTitle); }
QVariant albumArtist() const { return m_control->metaData(QtMultimediaKit::AlbumArtist); }
QVariant contributingArtist() const {
return m_control->metaData(QtMultimediaKit::ContributingArtist); }
QVariant composer() const { return m_control->metaData(QtMultimediaKit::Composer); }
QVariant conductor() const { return m_control->metaData(QtMultimediaKit::Conductor); }
QVariant lyrics() const { return m_control->metaData(QtMultimediaKit::Lyrics); }
QVariant mood() const { return m_control->metaData(QtMultimediaKit::Mood); }
QVariant trackNumber() const { return m_control->metaData(QtMultimediaKit::TrackNumber); }
QVariant trackCount() const { return m_control->metaData(QtMultimediaKit::TrackCount); }
QVariant coverArtUrlSmall() const {
return m_control->metaData(QtMultimediaKit::CoverArtUrlSmall); }
QVariant coverArtUrlLarge() const {
return m_control->metaData(QtMultimediaKit::CoverArtUrlLarge); }
QVariant resolution() const { return m_control->metaData(QtMultimediaKit::Resolution); }
QVariant pixelAspectRatio() const {
return m_control->metaData(QtMultimediaKit::PixelAspectRatio); }
QVariant videoFrameRate() const { return m_control->metaData(QtMultimediaKit::VideoFrameRate); }
QVariant videoBitRate() const { return m_control->metaData(QtMultimediaKit::VideoBitRate); }
QVariant videoCodec() const { return m_control->metaData(QtMultimediaKit::VideoCodec); }
QVariant posterUrl() const { return m_control->metaData(QtMultimediaKit::PosterUrl); }
QVariant chapterNumber() const { return m_control->metaData(QtMultimediaKit::ChapterNumber); }
QVariant director() const { return m_control->metaData(QtMultimediaKit::Director); }
QVariant leadPerformer() const { return m_control->metaData(QtMultimediaKit::LeadPerformer); }
QVariant writer() const { return m_control->metaData(QtMultimediaKit::Writer); }
Q_SIGNALS:
void metaDataChanged();
private:
QMetaDataReaderControl *m_control;
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativeMediaMetaData))
QT_END_HEADER
#endif

View File

@@ -0,0 +1,951 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qdeclarativevideo_p.h"
#include <qmediaplayercontrol.h>
#include <qmediaservice.h>
#include <private/qpaintervideosurface_p.h>
#include <qvideorenderercontrol.h>
QT_BEGIN_NAMESPACE
void QDeclarativeVideo::_q_nativeSizeChanged(const QSizeF &size)
{
setImplicitWidth(size.width());
setImplicitHeight(size.height());
}
void QDeclarativeVideo::_q_error(int errorCode, const QString &errorString)
{
m_error = QMediaPlayer::Error(errorCode);
m_errorString = errorString;
emit error(Error(errorCode), errorString);
emit errorChanged();
}
/*!
\qmlclass Video QDeclarativeVideo
\brief The Video element allows you to add videos to a scene.
\inherits Item
\ingroup qml-multimedia
This element is part of the \bold{QtMultimediaKit 1.1} module.
\qml
import Qt 4.7
import QtMultimediaKit 1.1
Video {
id: video
width : 800
height : 600
source: "video.avi"
MouseArea {
anchors.fill: parent
onClicked: {
video.play()
}
}
focus: true
Keys.onSpacePressed: video.paused = !video.paused
Keys.onLeftPressed: video.position -= 5000
Keys.onRightPressed: video.position += 5000
}
\endqml
The Video item supports untransformed, stretched, and uniformly scaled video presentation.
For a description of stretched uniformly scaled presentation, see the \l fillMode property
description.
The Video item is only visible when the \l hasVideo property is true and the video is playing.
\sa Audio
*/
/*!
\internal
\class QDeclarativeVideo
\brief The QDeclarativeVideo class provides a video item that you can add to a QDeclarativeView.
*/
QDeclarativeVideo::QDeclarativeVideo(QDeclarativeItem *parent)
: QDeclarativeItem(parent)
, m_graphicsItem(0)
{
}
QDeclarativeVideo::~QDeclarativeVideo()
{
shutdown();
delete m_graphicsItem;
}
/*!
\qmlproperty url Video::source
This property holds the source URL of the media.
*/
/*!
\qmlproperty url Video::autoLoad
This property indicates if loading of media should begin immediately.
Defaults to true, if false media will not be loaded until playback is started.
*/
/*!
\qmlproperty bool Video::playing
This property holds whether the media is playing.
Defaults to false, and can be set to true to start playback.
*/
/*!
\qmlproperty bool Video::paused
This property holds whether the media is paused.
Defaults to false, and can be set to true to pause playback.
*/
/*!
\qmlsignal Video::onStarted()
This handler is called when playback is started.
*/
/*!
\qmlsignal Video::onResumed()
This handler is called when playback is resumed from the paused state.
*/
/*!
\qmlsignal Video::onPaused()
This handler is called when playback is paused.
*/
/*!
\qmlsignal Video::onStopped()
This handler is called when playback is stopped.
*/
/*!
\qmlproperty enumeration Video::status
This property holds the status of media loading. It can be one of:
\list
\o NoMedia - no media has been set.
\o Loading - the media is currently being loaded.
\o Loaded - the media has been loaded.
\o Buffering - the media is buffering data.
\o Stalled - playback has been interrupted while the media is buffering data.
\o Buffered - the media has buffered data.
\o EndOfMedia - the media has played to the end.
\o InvalidMedia - the media cannot be played.
\o UnknownStatus - the status of the media is cannot be determined.
\endlist
*/
QDeclarativeVideo::Status QDeclarativeVideo::status() const
{
return Status(m_status);
}
/*!
\qmlproperty int Video::duration
This property holds the duration of the media in milliseconds.
If the media doesn't have a fixed duration (a live stream for example) this will be 0.
*/
/*!
\qmlproperty int Video::position
This property holds the current playback position in milliseconds.
*/
/*!
\qmlproperty real Video::volume
This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
*/
/*!
\qmlproperty bool Video::muted
This property holds whether the audio output is muted.
*/
/*!
\qmlproperty bool Video::hasAudio
This property holds whether the media contains audio.
*/
bool QDeclarativeVideo::hasAudio() const
{
return !m_complete ? false : m_playerControl->isAudioAvailable();
}
/*!
\qmlproperty bool Video::hasVideo
This property holds whether the media contains video.
*/
bool QDeclarativeVideo::hasVideo() const
{
return !m_complete ? false : m_playerControl->isVideoAvailable();
}
/*!
\qmlproperty real Video::bufferProgress
This property holds how much of the data buffer is currently filled, from 0.0 (empty) to 1.0
(full).
*/
/*!
\qmlproperty bool Video::seekable
This property holds whether position of the video can be changed.
*/
/*!
\qmlproperty real Video::playbackRate
This property holds the rate at which video is played at as a multiple of the normal rate.
*/
/*!
\qmlproperty enumeration Video::error
This property holds the error state of the video. It can be one of:
\list
\o NoError - there is no current error.
\o ResourceError - the video cannot be played due to a problem allocating resources.
\o FormatError - the video format is not supported.
\o NetworkError - the video cannot be played due to network issues.
\o AccessDenied - the video cannot be played due to insufficient permissions.
\o ServiceMissing - the video cannot be played because the media service could not be
instantiated.
\endlist
*/
QDeclarativeVideo::Error QDeclarativeVideo::error() const
{
return Error(m_error);
}
/*!
\qmlproperty string Video::errorString
This property holds a string describing the current error condition in more detail.
*/
/*!
\qmlsignal Video::onError(error, errorString)
This handler is called when an \l {QMediaPlayer::Error}{error} has
occurred. The errorString parameter may contain more detailed
information about the error.
*/
/*!
\qmlproperty enumeration Video::fillMode
Set this property to define how the video is scaled to fit the target area.
\list
\o Stretch - the video is scaled to fit.
\o PreserveAspectFit - the video is scaled uniformly to fit without cropping
\o PreserveAspectCrop - the video is scaled uniformly to fill, cropping if necessary
\endlist
The default fill mode is PreserveAspectFit.
*/
QDeclarativeVideo::FillMode QDeclarativeVideo::fillMode() const
{
return FillMode(m_graphicsItem->aspectRatioMode());
}
void QDeclarativeVideo::setFillMode(FillMode mode)
{
m_graphicsItem->setAspectRatioMode(Qt::AspectRatioMode(mode));
}
/*!
\qmlmethod Video::play()
Starts playback of the media.
Sets the \l playing property to true, and the \l paused property to false.
*/
void QDeclarativeVideo::play()
{
if (!m_complete)
return;
setPaused(false);
setPlaying(true);
}
/*!
\qmlmethod Video::pause()
Pauses playback of the media.
Sets the \l playing and \l paused properties to true.
*/
void QDeclarativeVideo::pause()
{
if (!m_complete)
return;
setPaused(true);
setPlaying(true);
}
/*!
\qmlmethod Video::stop()
Stops playback of the media.
Sets the \l playing and \l paused properties to false.
*/
void QDeclarativeVideo::stop()
{
if (!m_complete)
return;
setPlaying(false);
setPaused(false);
}
void QDeclarativeVideo::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
{
}
void QDeclarativeVideo::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
m_graphicsItem->setSize(newGeometry.size());
QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
}
void QDeclarativeVideo::classBegin()
{
m_graphicsItem = new QGraphicsVideoItem(this);
connect(m_graphicsItem, SIGNAL(nativeSizeChanged(QSizeF)),
this, SLOT(_q_nativeSizeChanged(QSizeF)));
setObject(this);
if (m_mediaService) {
connect(m_playerControl, SIGNAL(audioAvailableChanged(bool)),
this, SIGNAL(hasAudioChanged()));
connect(m_playerControl, SIGNAL(videoAvailableChanged(bool)),
this, SIGNAL(hasVideoChanged()));
m_mediaObject->bind(m_graphicsItem);
}
}
void QDeclarativeVideo::componentComplete()
{
QDeclarativeMediaBase::componentComplete();
}
QT_END_NAMESPACE
// ***************************************
// Documentation for meta-data properties.
// ***************************************
/*!
\qmlproperty variant Video::metaData.title
This property holds the tile of the media.
\sa {QtMultimediaKit::Title}
*/
/*!
\qmlproperty variant Video::metaData.subTitle
This property holds the sub-title of the media.
\sa {QtMultimediaKit::SubTitle}
*/
/*!
\qmlproperty variant Video::metaData.author
This property holds the author of the media.
\sa {QtMultimediaKit::Author}
*/
/*!
\qmlproperty variant Video::metaData.comment
This property holds a user comment about the media.
\sa {QtMultimediaKit::Comment}
*/
/*!
\qmlproperty variant Video::metaData.description
This property holds a description of the media.
\sa {QtMultimediaKit::Description}
*/
/*!
\qmlproperty variant Video::metaData.category
This property holds the category of the media
\sa {QtMultimediaKit::Category}
*/
/*!
\qmlproperty variant Video::metaData.genre
This property holds the genre of the media.
\sa {QtMultimediaKit::Genre}
*/
/*!
\qmlproperty variant Video::metaData.year
This property holds the year of release of the media.
\sa {QtMultimediaKit::Year}
*/
/*!
\qmlproperty variant Video::metaData.date
This property holds the date of the media.
\sa {QtMultimediaKit::Date}
*/
/*!
\qmlproperty variant Video::metaData.userRating
This property holds a user rating of the media in the range of 0 to 100.
\sa {QtMultimediaKit::UserRating}
*/
/*!
\qmlproperty variant Video::metaData.keywords
This property holds a list of keywords describing the media.
\sa {QtMultimediaKit::Keywords}
*/
/*!
\qmlproperty variant Video::metaData.language
This property holds the language of the media, as an ISO 639-2 code.
\sa {QtMultimediaKit::Language}
*/
/*!
\qmlproperty variant Video::metaData.publisher
This property holds the publisher of the media.
\sa {QtMultimediaKit::Publisher}
*/
/*!
\qmlproperty variant Video::metaData.copyright
This property holds the media's copyright notice.
\sa {QtMultimediaKit::Copyright}
*/
/*!
\qmlproperty variant Video::metaData.parentalRating
This property holds the parental rating of the media.
\sa {QtMultimediaKit::ParentalRating}
*/
/*!
\qmlproperty variant Video::metaData.ratingOrganisation
This property holds the name of the rating organisation responsible for the
parental rating of the media.
\sa {QtMultimediaKit::RatingOrganisation}
*/
/*!
\qmlproperty variant Video::metaData.size
This property property holds the size of the media in bytes.
\sa {QtMultimediaKit::Size}
*/
/*!
\qmlproperty variant Video::metaData.mediaType
This property holds the type of the media.
\sa {QtMultimediaKit::MediaType}
*/
/*!
\qmlproperty variant Video::metaData.audioBitRate
This property holds the bit rate of the media's audio stream ni bits per
second.
\sa {QtMultimediaKit::AudioBitRate}
*/
/*!
\qmlproperty variant Video::metaData.audioCodec
This property holds the encoding of the media audio stream.
\sa {QtMultimediaKit::AudioCodec}
*/
/*!
\qmlproperty variant Video::metaData.averageLevel
This property holds the average volume level of the media.
\sa {QtMultimediaKit::AverageLevel}
*/
/*!
\qmlproperty variant Video::metaData.channelCount
This property holds the number of channels in the media's audio stream.
\sa {QtMultimediaKit::ChannelCount}
*/
/*!
\qmlproperty variant Video::metaData.peakValue
This property holds the peak volume of media's audio stream.
\sa {QtMultimediaKit::PeakValue}
*/
/*!
\qmlproperty variant Video::metaData.sampleRate
This property holds the sample rate of the media's audio stream in hertz.
\sa {QtMultimediaKit::SampleRate}
*/
/*!
\qmlproperty variant Video::metaData.albumTitle
This property holds the title of the album the media belongs to.
\sa {QtMultimediaKit::AlbumTitle}
*/
/*!
\qmlproperty variant Video::metaData.albumArtist
This property holds the name of the principal artist of the album the media
belongs to.
\sa {QtMultimediaKit::AlbumArtist}
*/
/*!
\qmlproperty variant Video::metaData.contributingArtist
This property holds the names of artists contributing to the media.
\sa {QtMultimediaKit::ContributingArtist}
*/
/*!
\qmlproperty variant Video::metaData.composer
This property holds the composer of the media.
\sa {QtMultimediaKit::Composer}
*/
/*!
\qmlproperty variant Video::metaData.conductor
This property holds the conductor of the media.
\sa {QtMultimediaKit::Conductor}
*/
/*!
\qmlproperty variant Video::metaData.lyrics
This property holds the lyrics to the media.
\sa {QtMultimediaKit::Lyrics}
*/
/*!
\qmlproperty variant Video::metaData.mood
This property holds the mood of the media.
\sa {QtMultimediaKit::Mood}
*/
/*!
\qmlproperty variant Video::metaData.trackNumber
This property holds the track number of the media.
\sa {QtMultimediaKit::TrackNumber}
*/
/*!
\qmlproperty variant Video::metaData.trackCount
This property holds the number of track on the album containing the media.
\sa {QtMultimediaKit::TrackNumber}
*/
/*!
\qmlproperty variant Video::metaData.coverArtUrlSmall
This property holds the URL of a small cover art image.
\sa {QtMultimediaKit::CoverArtUrlSmall}
*/
/*!
\qmlproperty variant Video::metaData.coverArtUrlLarge
This property holds the URL of a large cover art image.
\sa {QtMultimediaKit::CoverArtUrlLarge}
*/
/*!
\qmlproperty variant Video::metaData.resolution
This property holds the dimension of an image or video.
\sa {QtMultimediaKit::Resolution}
*/
/*!
\qmlproperty variant Video::metaData.pixelAspectRatio
This property holds the pixel aspect ratio of an image or video.
\sa {QtMultimediaKit::PixelAspectRatio}
*/
/*!
\qmlproperty variant Video::metaData.videoFrameRate
This property holds the frame rate of the media's video stream.
\sa {QtMultimediaKit::VideoFrameRate}
*/
/*!
\qmlproperty variant Video::metaData.videoBitRate
This property holds the bit rate of the media's video stream in bits per
second.
\sa {QtMultimediaKit::VideoBitRate}
*/
/*!
\qmlproperty variant Video::metaData.videoCodec
This property holds the encoding of the media's video stream.
\sa {QtMultimediaKit::VideoCodec}
*/
/*!
\qmlproperty variant Video::metaData.posterUrl
This property holds the URL of a poster image.
\sa {QtMultimediaKit::PosterUrl}
*/
/*!
\qmlproperty variant Video::metaData.chapterNumber
This property holds the chapter number of the media.
\sa {QtMultimediaKit::ChapterNumber}
*/
/*!
\qmlproperty variant Video::metaData.director
This property holds the director of the media.
\sa {QtMultimediaKit::Director}
*/
/*!
\qmlproperty variant Video::metaData.leadPerformer
This property holds the lead performer in the media.
\sa {QtMultimediaKit::LeadPerformer}
*/
/*!
\qmlproperty variant Video::metaData.writer
This property holds the writer of the media.
\sa {QtMultimediaKit::Writer}
*/
// The remaining properties are related to photos, and are technically
// available but will certainly never have values.
#ifndef Q_QDOC
/*!
\qmlproperty variant Video::metaData.cameraManufacturer
\sa {QtMultimediaKit::CameraManufacturer}
*/
/*!
\qmlproperty variant Video::metaData.cameraModel
\sa {QtMultimediaKit::CameraModel}
*/
/*!
\qmlproperty variant Video::metaData.event
\sa {QtMultimediaKit::Event}
*/
/*!
\qmlproperty variant Video::metaData.subject
\sa {QtMultimediaKit::Subject}
*/
/*!
\qmlproperty variant Video::metaData.orientation
\sa {QtMultimediaKit::Orientation}
*/
/*!
\qmlproperty variant Video::metaData.exposureTime
\sa {QtMultimediaKit::ExposureTime}
*/
/*!
\qmlproperty variant Video::metaData.fNumber
\sa {QtMultimediaKit::FNumber}
*/
/*!
\qmlproperty variant Video::metaData.exposureProgram
\sa {QtMultimediaKit::ExposureProgram}
*/
/*!
\qmlproperty variant Video::metaData.isoSpeedRatings
\sa {QtMultimediaKit::ISOSpeedRatings}
*/
/*!
\qmlproperty variant Video::metaData.exposureBiasValue
\sa {QtMultimediaKit::ExposureBiasValue}
*/
/*!
\qmlproperty variant Video::metaData.dateTimeDigitized
\sa {QtMultimediaKit::DateTimeDigitized}
*/
/*!
\qmlproperty variant Video::metaData.subjectDistance
\sa {QtMultimediaKit::SubjectDistance}
*/
/*!
\qmlproperty variant Video::metaData.meteringMode
\sa {QtMultimediaKit::MeteringMode}
*/
/*!
\qmlproperty variant Video::metaData.lightSource
\sa {QtMultimediaKit::LightSource}
*/
/*!
\qmlproperty variant Video::metaData.flash
\sa {QtMultimediaKit::Flash}
*/
/*!
\qmlproperty variant Video::metaData.focalLength
\sa {QtMultimediaKit::FocalLength}
*/
/*!
\qmlproperty variant Video::metaData.exposureMode
\sa {QtMultimediaKit::ExposureMode}
*/
/*!
\qmlproperty variant Video::metaData.whiteBalance
\sa {QtMultimediaKit::WhiteBalance}
*/
/*!
\qmlproperty variant Video::metaData.DigitalZoomRatio
\sa {QtMultimediaKit::DigitalZoomRatio}
*/
/*!
\qmlproperty variant Video::metaData.focalLengthIn35mmFilm
\sa {QtMultimediaKit::FocalLengthIn35mmFile}
*/
/*!
\qmlproperty variant Video::metaData.sceneCaptureType
\sa {QtMultimediaKit::SceneCaptureType}
*/
/*!
\qmlproperty variant Video::metaData.gainControl
\sa {QtMultimediaKit::GainControl}
*/
/*!
\qmlproperty variant Video::metaData.contrast
\sa {QtMultimediaKit::contrast}
*/
/*!
\qmlproperty variant Video::metaData.saturation
\sa {QtMultimediaKit::Saturation}
*/
/*!
\qmlproperty variant Video::metaData.sharpness
\sa {QtMultimediaKit::Sharpness}
*/
/*!
\qmlproperty variant Video::metaData.deviceSettingDescription
\sa {QtMultimediaKit::DeviceSettingDescription}
*/
#endif
#include "moc_qdeclarativevideo_p.cpp"

View File

@@ -0,0 +1,202 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDECLARATIVEVIDEO_H
#define QDECLARATIVEVIDEO_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qdeclarativemediabase_p.h"
#include <qgraphicsvideoitem.h>
#include <QtCore/qbasictimer.h>
#include <QtDeclarative/qdeclarativeitem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QTimerEvent;
class QVideoSurfaceFormat;
class QDeclarativeVideo : public QDeclarativeItem, public QDeclarativeMediaBase
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
Q_PROPERTY(int position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
Q_PROPERTY(bool hasAudio READ hasAudio NOTIFY hasAudioChanged)
Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged)
Q_PROPERTY(int bufferProgress READ bufferProgress NOTIFY bufferProgressChanged)
Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged)
Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
Q_PROPERTY(Error error READ error NOTIFY errorChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode)
Q_PROPERTY(QDeclarativeMediaMetaData *metaData READ metaData CONSTANT)
Q_ENUMS(FillMode)
Q_ENUMS(Status)
Q_ENUMS(Error)
public:
enum FillMode
{
Stretch = Qt::IgnoreAspectRatio,
PreserveAspectFit = Qt::KeepAspectRatio,
PreserveAspectCrop = Qt::KeepAspectRatioByExpanding
};
enum Status
{
UnknownStatus = QMediaPlayer::UnknownMediaStatus,
NoMedia = QMediaPlayer::NoMedia,
Loading = QMediaPlayer::LoadingMedia,
Loaded = QMediaPlayer::LoadedMedia,
Stalled = QMediaPlayer::StalledMedia,
Buffering = QMediaPlayer::BufferingMedia,
Buffered = QMediaPlayer::BufferedMedia,
EndOfMedia = QMediaPlayer::EndOfMedia,
InvalidMedia = QMediaPlayer::InvalidMedia
};
enum Error
{
NoError = QMediaPlayer::NoError,
ResourceError = QMediaPlayer::ResourceError,
FormatError = QMediaPlayer::FormatError,
NetworkError = QMediaPlayer::NetworkError,
AccessDenied = QMediaPlayer::AccessDeniedError,
ServiceMissing = QMediaPlayer::ServiceMissingError
};
QDeclarativeVideo(QDeclarativeItem *parent = 0);
~QDeclarativeVideo();
bool hasAudio() const;
bool hasVideo() const;
FillMode fillMode() const;
void setFillMode(FillMode mode);
Status status() const;
Error error() const;
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
void classBegin();
void componentComplete();
public Q_SLOTS:
void play();
void pause();
void stop();
Q_SIGNALS:
void sourceChanged();
void autoLoadChanged();
void playingChanged();
void pausedChanged();
void loopCountChanged();
void started();
void resumed();
void paused();
void stopped();
void statusChanged();
void durationChanged();
void positionChanged();
void volumeChanged();
void mutedChanged();
void hasAudioChanged();
void hasVideoChanged();
void bufferProgressChanged();
void seekableChanged();
void playbackRateChanged();
void errorChanged();
void error(QDeclarativeVideo::Error error, const QString &errorString);
protected:
void geometryChanged(const QRectF &geometry, const QRectF &);
private Q_SLOTS:
void _q_nativeSizeChanged(const QSizeF &size);
void _q_error(int, const QString &);
private:
Q_DISABLE_COPY(QDeclarativeVideo)
QGraphicsVideoItem *m_graphicsItem;
Q_PRIVATE_SLOT(mediaBase(), void _q_statusChanged())
inline QDeclarativeMediaBase *mediaBase() { return this; }
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativeVideo))
QT_END_HEADER
#endif

View File

@@ -0,0 +1 @@
plugin declarative_multimedia

View File

@@ -0,0 +1,38 @@
load(qt_module)
symbian:load(qt_plugin)
TEMPLATE = lib
CONFIG += qt plugin
win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release
isEmpty(TARGETPATH) {
error("qimportbase.pri: You must provide a TARGETPATH!")
}
isEmpty(TARGET) {
error("qimportbase.pri: You must provide a TARGET!")
}
QMLDIRFILE = $${_PRO_FILE_PWD_}/qmldir
copy2build.input = QMLDIRFILE
copy2build.output = $$QT.declarative.imports/$$TARGETPATH/qmldir
!contains(TEMPLATE_PREFIX, vc):copy2build.variable_out = PRE_TARGETDEPS
copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
copy2build.name = COPY ${QMAKE_FILE_IN}
copy2build.CONFIG += no_link
# `clean' should leave the build in a runnable state, which means it shouldn't delete qmldir
copy2build.CONFIG += no_clean
QMAKE_EXTRA_COMPILERS += copy2build
TARGET = $$qtLibraryTarget($$TARGET)
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
load(qt_targets)
wince*:LIBS += $$QMAKE_LIBS_GUI
symbian: {
TARGET.EPOCALLOWDLLDATA=1
TARGET.CAPABILITY = All -Tcb
load(armcc_warnings)
}

View File

@@ -0,0 +1,40 @@
PKG_NAME := qt-mobility
SPECFILE = $(addsuffix .spec, $(PKG_NAME))
YAMLFILE = $(addsuffix .yaml, $(PKG_NAME))
first: custom-help
include /usr/share/meego-packaging-tools/Makefile.common
custom-help: help
@echo "The above are common MeeGo packaging targets."
@echo "$(PKG_NAME) also has these additional targets:"
@echo " spec-git Create spec file, with options appropriate for git"
@echo " build-trunk-i686 Do a local i686 build against Trunk, without using OBS"
@echo " build-trunk-testing-i686 Do a local i686 build against Trunk:Testing, without using OBS"
spec-git:
specify --skip-scm --not-download --non-interactive
git-archive: spec-git
@VER=$$(sed -n -r -e 's|^Version: +||p' $(SPECFILE)); \
TARGZ=$$(sed -n -r \
-e 's|^Source0:.*/([^/]+)$$|\1|' \
-e 's|%\{name\}|$(PKG_NAME)|' \
-e "s|%\{version\}|$$VER|" \
-e 's|.tar.gz||p' \
$(SPECFILE) ); \
DIR="$$PWD"; \
cd $$(git rev-parse --git-dir) && \
echo "Creating $$DIR/$$TARGZ.tar.gz ..." && \
git archive HEAD --prefix=$$TARGZ/ --format=tar | gzip > "$$DIR/$$TARGZ.tar.gz"
build-no-obs = sudo build $(SPECFILE) --repository $1 --arch $2
build-no-obs-deps: /usr/bin/build git-archive
build-trunk-i686: build-no-obs-deps
$(call build-no-obs,http://download.meego.com/live/Trunk/standard/,i686)
build-trunk-testing-i686: build-no-obs-deps
$(call build-no-obs,http://download.meego.com/live/Trunk:/Testing/standard/,i686)

95
src/meegoinstalls/README Normal file
View File

@@ -0,0 +1,95 @@
This directory contains the MeeGo.com packaging metadata for Qt Mobility,
for use with the MeeGo.com OpenSuSE Build Service (OBS).
Please see http://build.meego.com/ for more information about OBS.
Quick Start: run `make' in this directory to see some useful things you
can do.
PATCHES
=======
At the time of writing, there are some MeeGo-specific patches hosted
on the MeeGo OBS. These patches are unable to be hosted in the Mobility
git repository at this time.
In order to successfully build Mobility for MeeGo, you must also obtain
these patches, or you must modify qt-mobility.yaml and qt-mobility.spec
to remove the usage of the patches.
Please do not add any more patches.
HOW TO MAKE CHANGES
===================
Within this directory, there is a yaml file and a spec file. The yaml
file is maintained by hand; the spec file is partially generated from the
yaml file, but partially maintained by hand also, in specially marked
sections.
The command used to generate the spec file from the yaml file is `specify'.
This is part of a tool named Spectacle. This can be installed from the
MeeGo tools repositories. It does not require a full MeeGo SDK install.
For example, on Ubuntu:
$ sudo /bin/sh -c 'echo deb http://repo.meego.com/MeeGo/tools/repos/ubuntu/10.04/ / > /etc/apt/sources.list.d/meego-tools.list'
$ gpg --keyserver pgpkeys.mit.edu --recv 0BC7BEC479FC1F8A && gpg --export --armor 0BC7BEC479FC1F8A | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install meego-packaging-tools
Once you have installed meego-packaging-tools, you can run `make spec-git'
in this directory to regenerate the spec file from the yaml file.
The spec file and yaml file should be maintained together, so if you
modify the yaml file, you should do `make spec-git' and put the
modifications to the spec file in the same commit.
Please see http://wiki.meego.com/Spectacle for more information about
spectacle.
HOW TO BUILD
============
Note: these instructions are not canonical or supported in any way.
They are here as a quick start for people who want to contribute to
Qt Mobility and do not know how to compile for MeeGo.
The most accurate way to build is to use the OpenSuSE build service
on build.meego.com. Unfortunately, at time of writing, anonymous
access to this service is not available. Therefore, using build.meego.com
is not an option for most people.
However, a fairly accurate build can still be done using the `build' command
and referring to the live MeeGo repos.
Abbreviated example of how to install `build' for Ubuntu:
$ sudo /bin/sh -c 'echo deb http://repo.meego.com/MeeGo/tools/repos/ubuntu/10.04/ / > /etc/apt/sources.list.d/meego-tools.list'
$ gpg --keyserver pgpkeys.mit.edu --recv 0BC7BEC479FC1F8A && gpg --export --armor 0BC7BEC479FC1F8A | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install build
$ gpg --keyserver pgpkeys.mit.edu --recv 79FC1F8A && gpg --export --armor 79FC1F8A | sudo rpm --import -
Then, to do the build (for i686):
$ make build-trunk-i686
Or, to use the Trunk:Testing repository (which may contain newer versions of some packages):
$ make build-trunk-testing-i686
These builds will take place in a chroot, and hence will require root access.
They will attempt to use `sudo' for this.
If you hit an error, `rpm: error while loading shared libraries: liblua-5.1.so',
edit /usr/lib/build/configs/default.conf and add liblua to one of the `Preinstall:' lines
(see http://comments.gmane.org/gmane.comp.handhelds.meego.devel/7139 )

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,353 @@
Name: qt-mobility
Summary: APIs for mobile device functionality
Version: 1.1.0+git2438
Release: 1
Group: System/Libraries
License: LGPLv2.1 with exception or GPLv3
URL: http://qt.gitorious.org/qt-mobility
Sources:
- http://get.qt.nokia.com/qt/add-ons/%{name}-opensource-src-%{version}.tar.gz
SourcePrefix: "%{name}-opensource-src-%{version}"
Patches:
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality. These
APIs allow the developer to use these features with ease from one framework and
apply them to phones, netbooks and non-mobile personal computers.
Requires:
- libqtconnectivity1 = %{version}
- libqtcontacts1 = %{version}
- libqtfeedback1 = %{version}
- libqtgallery1 = %{version}
- libqtlocation1 = %{version}
- libqtmessaging1 = %{version}
- libqtmultimediakit1 = %{version}
- libqtorganizer1 = %{version}
- libqtpublishsubscribe1 = %{version}
- libqtsensors1 = %{version}
- libqtserviceframework1 = %{version}
- libqtsysteminfo1 = %{version}
- libqtversit1 = %{version}
- libqtversitorganizer1 = %{version}
PkgConfigBR:
- QtGui
- QtOpenGL
- alsa
- blkid
- bluez
- connman
- contextsubscriber-1.0
- gconf-2.0
- geoclue
- gstreamer-plugins-bad-free-0.10
- gstreamer-plugins-base-0.10
- gypsy
- libiphb
- libpulse
- libmkcal
- meegotouch
- qttracker
- qmfclient
- sensord
- udev
- x11
- xext
- xrandr
- xrender
- xv
- QtSparql
- QtSparqlTrackerExtensions
PkgBR:
- qt-devel-tools
Configure: none
Builder: none
RunFdupes: "%{_datadir}/qtmobility/translations"
SubPackages:
- Name: devel
Summary: APIs for mobile device functionality - development files
Group: Development/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the development files needed to build Qt applications
using Qt Mobility libraries.
Requires:
- servicefw
- Name: libqtconnectivity1
AsWholeName: yes
Summary: Qt Mobility Connectivity module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Connectivity API. It provides APIs for working with
local devices.
- Name: libqtcontacts1
AsWholeName: yes
Summary: Qt Mobility Contacts module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains an API enabling clients to request contact data from
local or remote backends.
- Name: libqtfeedback1
AsWholeName: yes
Summary: Qt Mobility Feedback module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Feedback API. It enables a client to control
the vibration of the device or the piezo feedback from the screen.
- Name: libqtgallery1
AsWholeName: yes
Summary: Qt Mobility Document Gallery module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains an API for accessing collections of documents and media
and their meta-data.
- Name: libqtlocation1
AsWholeName: yes
Summary: Qt Mobility Location module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Location API. It provides a library for distributing
and receiving location data using arbitrary data sources.
- Name: libqtmessaging1
AsWholeName: yes
Summary: Qt Mobility Messaging module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Messaging API. It is a common interface for handling
SMS, MMS, MIME Email and TNEF Email messages.
- Name: libqtmultimediakit1
AsWholeName: yes
Summary: Qt Mobility MultimediaKit module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains a set of APIs to play and record media, and manage a
collection of media content.
- Name: libqtorganizer1
AsWholeName: yes
Summary: Qt Mobility Organizer module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains an API for management of calendar, scheduling and
personal data from local or remote backends. It includes the ability to create,
edit, list, delete and lookup organizer information whether it is stored
locally or remotely.
- Name: libqtpublishsubscribe1
AsWholeName: yes
Summary: Qt Mobility Publish and Subscribe module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Publish and Subscribe API (containing Value Space).
It enables applications to read item values, navigate through and subscribe to
change notifications.
- Name: libqtsensors1
AsWholeName: yes
Summary: Qt Mobility Sensors module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Sensors API. It provides access to sensors.
Requires:
- libqtsql4-sqlite
- sensorfw
- Name: libqtserviceframework1
AsWholeName: yes
Summary: Qt Mobility Service Framework module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains a set of APIs to that allows clients to discover and
instantiate arbitrary services.
- Name: libqtsysteminfo1
AsWholeName: yes
Summary: Qt Mobility System Information module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains a set of APIs to discover system related information and
capabilities.
- Name: libqtversit1
AsWholeName: yes
Summary: Qt Mobility Versit (vCard) module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains an API to manage Versit documents, such as vCards.
- Name: libqtversitorganizer1
AsWholeName: yes
Summary: Qt Mobility Versit (Organizer) module
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains an API to manage Versit documents, such as iCalendar
documents. It interfaces the Organizer API and uses the same framework as for
vCards.
- Name: libdeclarative-contacts
AsWholeName: yes
Summary: Qt Mobility Contacts QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Contacts QML plugin for QtDeclarative.
- Name: libdeclarative-feedback
AsWholeName: yes
Summary: Qt Mobility Feedback QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Feedback QML plugin for QtDeclarative.
- Name: libdeclarative-gallery
AsWholeName: yes
Summary: Qt Mobility Document Gallery QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Document Gallery QML plugin for QtDeclarative.
- Name: libdeclarative-location
AsWholeName: yes
Summary: Qt Mobility Location QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Location QML plugin for QtDeclarative.
- Name: libdeclarative-messaging
AsWholeName: yes
Summary: Qt Mobility Messaging QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Messaging QML plugin for QtDeclarative.
- Name: libdeclarative-multimedia
AsWholeName: yes
Summary: Qt Mobility Multimedia QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Multimedia QML plugin for QtDeclarative.
- Name: libdeclarative-organizer
AsWholeName: yes
Summary: Qt Mobility Organizer QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Organizer QML plugin for QtDeclarative.
- Name: libdeclarative-publishsubscribe
AsWholeName: yes
Summary: Qt Mobility Publish and Subscribe QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Publish and Subscribe QML plugin for QtDeclarative.
- Name: libdeclarative-sensors
AsWholeName: yes
Summary: Qt Mobility Sensors Framework QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Sensors QML plugin for QtDeclarative.
- Name: libdeclarative-serviceframework
AsWholeName: yes
Summary: Qt Mobility Service Framework QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Service Framework QML plugin for QtDeclarative.
- Name: libdeclarative-systeminfo
AsWholeName: yes
Summary: Qt Mobility System Information QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the System Information QML plugin for QtDeclarative.
- Name: libdeclarative-connectivity
AsWholeName: yes
Summary: Qt Mobility Connectivity QML plugin
Group: System/Libraries
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Connectivity QML plugin for QtDeclarative.
- Name: servicefw
AsWholeName: yes
Summary: Qt Mobility Service Framework tool
Group: Development/Tools
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains the Service Framework tool (servicefw). It allows
to register services and make them available over the Service Framework.
- Name: examples
Summary: Qt Mobility examples
Group: System/X11
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains Qt Mobility examples.
- Name: l10n
Summary: APIs for mobile device functionality - localization files
Group: System/I18n
Description: |
Qt Mobility delivers a set of new APIs for mobile device functionality.
This package contains Qt Mobility translations.

View File

@@ -0,0 +1,79 @@
INCLUDEPATH += audio
PUBLIC_HEADERS += audio/qaudio.h \
audio/qaudioformat.h \
audio/qaudioinput.h \
audio/qaudiooutput.h \
audio/qaudiodeviceinfo.h \
audio/qaudiosystemplugin.h \
audio/qaudiosystem.h
PRIVATE_HEADERS += audio/qaudiodevicefactory_p.h audio/qaudiopluginloader_p.h
SOURCES += audio/qaudio.cpp \
audio/qaudioformat.cpp \
audio/qaudiodeviceinfo.cpp \
audio/qaudiooutput.cpp \
audio/qaudioinput.cpp \
audio/qaudiosystemplugin.cpp \
audio/qaudiosystem.cpp \
audio/qaudiodevicefactory.cpp \
audio/qaudiopluginloader.cpp
mac {
PRIVATE_HEADERS += audio/qaudioinput_mac_p.h \
audio/qaudiooutput_mac_p.h \
audio/qaudiodeviceinfo_mac_p.h \
audio/qaudio_mac_p.h
SOURCES += audio/qaudiodeviceinfo_mac_p.cpp \
audio/qaudiooutput_mac_p.cpp \
audio/qaudioinput_mac_p.cpp \
audio/qaudio_mac.cpp
LIBS += -framework ApplicationServices -framework CoreAudio -framework AudioUnit -framework AudioToolbox
}
win32 {
PRIVATE_HEADERS += audio/qaudioinput_win32_p.h audio/qaudiooutput_win32_p.h audio/qaudiodeviceinfo_win32_p.h
SOURCES += audio/qaudiodeviceinfo_win32_p.cpp \
audio/qaudiooutput_win32_p.cpp \
audio/qaudioinput_win32_p.cpp
!wince*:LIBS += -lwinmm
wince*:LIBS += -lcoredll
LIBS += -lstrmiids -lole32 -loleaut32
}
symbian {
INCLUDEPATH += $${EPOCROOT}epoc32/include/mmf/common
INCLUDEPATH += $${EPOCROOT}epoc32/include/mmf/server
PRIVATE_HEADERS += audio/qaudio_symbian_p.h \
audio/qaudiodeviceinfo_symbian_p.h \
audio/qaudioinput_symbian_p.h \
audio/qaudiooutput_symbian_p.h
SOURCES += audio/qaudio_symbian_p.cpp \
audio/qaudiodeviceinfo_symbian_p.cpp \
audio/qaudioinput_symbian_p.cpp \
audio/qaudiooutput_symbian_p.cpp
LIBS += -lmmfdevsound
}
unix:!mac:!symbian {
contains(pulseaudio_enabled, yes) {
DEFINES += QT_NO_AUDIO_BACKEND
}
else:contains(QT_CONFIG, alsa) {
linux-*|freebsd-*|openbsd-* {
DEFINES += HAS_ALSA
PRIVATE_HEADERS += audio/qaudiooutput_alsa_p.h audio/qaudioinput_alsa_p.h audio/qaudiodeviceinfo_alsa_p.h
SOURCES += audio/qaudiodeviceinfo_alsa_p.cpp \
audio/qaudiooutput_alsa_p.cpp \
audio/qaudioinput_alsa_p.cpp
LIBS_PRIVATE += -lasound
}
}
}

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qaudio.h>
QT_BEGIN_NAMESPACE
namespace QAudio
{
class RegisterMetaTypes
{
public:
RegisterMetaTypes()
{
qRegisterMetaType<QAudio::Error>();
qRegisterMetaType<QAudio::State>();
qRegisterMetaType<QAudio::Mode>();
}
} _register;
}
/*
\namespace QAudio
\brief The QAudio namespace contains enums used by the audio classes.
\inmodule QtMultimediaKit
\ingroup multimedia
*/
/*
\enum QAudio::Error
\value NoError No errors have occurred
\value OpenError An error occurred opening the audio device
\value IOError An error occurred during read/write of audio device
\value UnderrunError Audio data is not being fed to the audio device at a fast enough rate
\value FatalError A non-recoverable error has occurred, the audio device is not usable at this time.
*/
/*
\enum QAudio::State
\value ActiveState Audio data is being processed, this state is set after start() is called
and while audio data is available to be processed.
\value SuspendedState The audio device is in a suspended state, this state will only be entered
after suspend() is called.
\value StoppedState The audio device is closed, and is not processing any audio data
\value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state
is set after start() is called and while no audio data is available to be processed.
*/
/*
\enum QAudio::Mode
\value AudioOutput audio output device
\value AudioInput audio input device
*/
QT_END_NAMESPACE

View File

@@ -0,0 +1,71 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIO_H
#define QAUDIO_H
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include <QtCore/qmetatype.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
//QTM_SYNC_HEADER_EXPORT QAudio
namespace QAudio
{
enum Error { NoError, OpenError, IOError, UnderrunError, FatalError };
enum State { ActiveState, SuspendedState, StoppedState, IdleState };
enum Mode { AudioInput, AudioOutput };
}
QT_END_NAMESPACE
QT_END_HEADER
Q_DECLARE_METATYPE(QAudio::Error)
Q_DECLARE_METATYPE(QAudio::State)
Q_DECLARE_METATYPE(QAudio::Mode)
#endif // QAUDIO_H

View File

@@ -0,0 +1,145 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudio_mac_p.h"
QT_BEGIN_NAMESPACE
// Debugging
QDebug operator<<(QDebug dbg, const QAudioFormat& audioFormat)
{
dbg.nospace() << "QAudioFormat(" <<
audioFormat.frequency() << "," <<
audioFormat.channels() << "," <<
audioFormat.sampleSize()<< "," <<
audioFormat.codec() << "," <<
audioFormat.byteOrder() << "," <<
audioFormat.sampleType() << ")";
return dbg.space();
}
// Conversion
QAudioFormat toQAudioFormat(AudioStreamBasicDescription const& sf)
{
QAudioFormat audioFormat;
audioFormat.setFrequency(sf.mSampleRate);
audioFormat.setChannels(sf.mChannelsPerFrame);
audioFormat.setSampleSize(sf.mBitsPerChannel);
audioFormat.setCodec(QString::fromLatin1("audio/pcm"));
audioFormat.setByteOrder((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian);
QAudioFormat::SampleType type = QAudioFormat::UnSignedInt;
if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
type = QAudioFormat::SignedInt;
else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
type = QAudioFormat::Float;
audioFormat.setSampleType(type);
return audioFormat;
}
AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& audioFormat)
{
AudioStreamBasicDescription sf;
sf.mFormatFlags = kAudioFormatFlagIsPacked;
sf.mSampleRate = audioFormat.frequency();
sf.mFramesPerPacket = 1;
sf.mChannelsPerFrame = audioFormat.channels();
sf.mBitsPerChannel = audioFormat.sampleSize();
sf.mBytesPerFrame = sf.mChannelsPerFrame * (sf.mBitsPerChannel / 8);
sf.mBytesPerPacket = sf.mFramesPerPacket * sf.mBytesPerFrame;
sf.mFormatID = kAudioFormatLinearPCM;
switch (audioFormat.sampleType()) {
case QAudioFormat::SignedInt: sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger; break;
case QAudioFormat::UnSignedInt: /* default */ break;
case QAudioFormat::Float: sf.mFormatFlags |= kAudioFormatFlagIsFloat; break;
case QAudioFormat::Unknown: default: break;
}
if (audioFormat.byteOrder() == QAudioFormat::BigEndian)
sf.mFormatFlags |= kAudioFormatFlagIsBigEndian;
return sf;
}
// QAudioRingBuffer
QAudioRingBuffer::QAudioRingBuffer(int bufferSize):
m_bufferSize(bufferSize)
{
m_buffer = new char[m_bufferSize];
reset();
}
QAudioRingBuffer::~QAudioRingBuffer()
{
delete m_buffer;
}
int QAudioRingBuffer::used() const
{
return m_bufferUsed;
}
int QAudioRingBuffer::free() const
{
return m_bufferSize - m_bufferUsed;
}
int QAudioRingBuffer::size() const
{
return m_bufferSize;
}
void QAudioRingBuffer::reset()
{
m_readPos = 0;
m_writePos = 0;
m_bufferUsed = 0;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,142 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIO_MAC_P_H
#define QAUDIO_MAC_P_H
#include <CoreAudio/CoreAudio.h>
#include <QtCore/qdebug.h>
#include <QtCore/qatomic.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
extern QDebug operator<<(QDebug dbg, const QAudioFormat& audioFormat);
extern QAudioFormat toQAudioFormat(const AudioStreamBasicDescription& streamFormat);
extern AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& audioFormat);
class QAudioRingBuffer
{
public:
typedef QPair<char*, int> Region;
QAudioRingBuffer(int bufferSize);
~QAudioRingBuffer();
Region acquireReadRegion(int size)
{
const int used = m_bufferUsed.fetchAndAddAcquire(0);
if (used > 0) {
const int readSize = qMin(size, qMin(m_bufferSize - m_readPos, used));
return readSize > 0 ? Region(m_buffer + m_readPos, readSize) : Region(0, 0);
}
return Region(0, 0);
}
void releaseReadRegion(Region const& region)
{
m_readPos = (m_readPos + region.second) % m_bufferSize;
m_bufferUsed.fetchAndAddRelease(-region.second);
}
Region acquireWriteRegion(int size)
{
const int free = m_bufferSize - m_bufferUsed.fetchAndAddAcquire(0);
if (free > 0) {
const int writeSize = qMin(size, qMin(m_bufferSize - m_writePos, free));
return writeSize > 0 ? Region(m_buffer + m_writePos, writeSize) : Region(0, 0);
}
return Region(0, 0);
}
void releaseWriteRegion(Region const& region)
{
m_writePos = (m_writePos + region.second) % m_bufferSize;
m_bufferUsed.fetchAndAddRelease(region.second);
}
int used() const;
int free() const;
int size() const;
void reset();
private:
int m_bufferSize;
int m_readPos;
int m_writePos;
char* m_buffer;
QAtomicInt m_bufferUsed;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIO_MAC_P_H

View File

@@ -0,0 +1,663 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudio_symbian_p.h"
#include <mmffourcc.h>
QT_BEGIN_NAMESPACE
namespace SymbianAudio {
namespace Utils {
//-----------------------------------------------------------------------------
// Static data
//-----------------------------------------------------------------------------
// Sample rate / frequency
typedef TMMFSampleRate SampleRateNative;
typedef int SampleRateQt;
const int SampleRateCount = 12;
const SampleRateNative SampleRateListNative[SampleRateCount] = {
EMMFSampleRate8000Hz
, EMMFSampleRate11025Hz
, EMMFSampleRate12000Hz
, EMMFSampleRate16000Hz
, EMMFSampleRate22050Hz
, EMMFSampleRate24000Hz
, EMMFSampleRate32000Hz
, EMMFSampleRate44100Hz
, EMMFSampleRate48000Hz
, EMMFSampleRate64000Hz
, EMMFSampleRate88200Hz
, EMMFSampleRate96000Hz
};
const SampleRateQt SampleRateListQt[SampleRateCount] = {
8000
, 11025
, 12000
, 16000
, 22050
, 24000
, 32000
, 44100
, 48000
, 64000
, 88200
, 96000
};
// Channels
typedef TMMFMonoStereo ChannelsNative;
typedef int ChannelsQt;
const int ChannelsCount = 2;
const ChannelsNative ChannelsListNative[ChannelsCount] = {
EMMFMono
, EMMFStereo
};
const ChannelsQt ChannelsListQt[ChannelsCount] = {
1
, 2
};
// Encoding
const int EncodingCount = 6;
const TUint32 EncodingFourCC[EncodingCount] = {
KMMFFourCCCodePCM8 // 0
, KMMFFourCCCodePCMU8 // 1
, KMMFFourCCCodePCM16 // 2
, KMMFFourCCCodePCMU16 // 3
, KMMFFourCCCodePCM16B // 4
, KMMFFourCCCodePCMU16B // 5
};
// The characterised DevSound API specification states that the iEncoding
// field in TMMFCapabilities is ignored, and that the FourCC should be used
// to specify the PCM encoding.
// See "SGL.GT0287.102 Multimedia DevSound Baseline Compatibility.doc" in the
// mm_info/mm_docs repository.
const TMMFSoundEncoding EncodingNative[EncodingCount] = {
EMMFSoundEncoding16BitPCM // 0
, EMMFSoundEncoding16BitPCM // 1
, EMMFSoundEncoding16BitPCM // 2
, EMMFSoundEncoding16BitPCM // 3
, EMMFSoundEncoding16BitPCM // 4
, EMMFSoundEncoding16BitPCM // 5
};
const int EncodingSampleSize[EncodingCount] = {
8 // 0
, 8 // 1
, 16 // 2
, 16 // 3
, 16 // 4
, 16 // 5
};
const QAudioFormat::Endian EncodingByteOrder[EncodingCount] = {
QAudioFormat::LittleEndian // 0
, QAudioFormat::LittleEndian // 1
, QAudioFormat::LittleEndian // 2
, QAudioFormat::LittleEndian // 3
, QAudioFormat::BigEndian // 4
, QAudioFormat::BigEndian // 5
};
const QAudioFormat::SampleType EncodingSampleType[EncodingCount] = {
QAudioFormat::SignedInt // 0
, QAudioFormat::UnSignedInt // 1
, QAudioFormat::SignedInt // 2
, QAudioFormat::UnSignedInt // 3
, QAudioFormat::SignedInt // 4
, QAudioFormat::UnSignedInt // 5
};
//-----------------------------------------------------------------------------
// Private functions
//-----------------------------------------------------------------------------
// Helper functions for implementing parameter conversions
template<typename Input>
bool findValue(const Input *inputArray, int length, Input input, int &index) {
bool result = false;
for (int i=0; !result && i<length; ++i)
if (inputArray[i] == input) {
index = i;
result = true;
}
return result;
}
template<typename Input, typename Output>
bool convertValue(const Input *inputArray, const Output *outputArray,
int length, Input input, Output &output) {
int index;
const bool result = findValue<Input>(inputArray, length, input, index);
if (result)
output = outputArray[index];
return result;
}
/**
* Macro which is used to generate the implementation of the conversion
* functions. The implementation is just a wrapper around the templated
* convertValue function, e.g.
*
* CONVERSION_FUNCTION_IMPL(SampleRate, Qt, Native)
*
* expands to
*
* bool SampleRateQtToNative(int input, TMMFSampleRate &output) {
* return convertValue<SampleRateQt, SampleRateNative>
* (SampleRateListQt, SampleRateListNative, SampleRateCount,
* input, output);
* }
*/
#define CONVERSION_FUNCTION_IMPL(FieldLc, Field, Input, Output) \
bool FieldLc##Input##To##Output(Field##Input input, Field##Output &output) { \
return convertValue<Field##Input, Field##Output>(Field##List##Input, \
Field##List##Output, Field##Count, input, output); \
}
//-----------------------------------------------------------------------------
// Local helper functions
//-----------------------------------------------------------------------------
CONVERSION_FUNCTION_IMPL(sampleRate, SampleRate, Qt, Native)
CONVERSION_FUNCTION_IMPL(sampleRate, SampleRate, Native, Qt)
CONVERSION_FUNCTION_IMPL(channels, Channels, Qt, Native)
CONVERSION_FUNCTION_IMPL(channels, Channels, Native, Qt)
bool sampleInfoQtToNative(int inputSampleSize,
QAudioFormat::Endian inputByteOrder,
QAudioFormat::SampleType inputSampleType,
TUint32 &outputFourCC,
TMMFSoundEncoding &outputEncoding) {
bool found = false;
for (int i=0; i<EncodingCount && !found; ++i) {
if ( EncodingSampleSize[i] == inputSampleSize
&& EncodingByteOrder[i] == inputByteOrder
&& EncodingSampleType[i] == inputSampleType) {
outputFourCC = EncodingFourCC[i];
outputEncoding = EncodingNative[i]; // EMMFSoundEncoding16BitPCM
found = true;
}
}
return found;
}
void capabilitiesNativeToQt(const TMMFCapabilities &caps,
const TFourCC &fourcc,
QList<int> &frequencies,
QList<int> &channels,
QList<int> &sampleSizes,
QList<QAudioFormat::Endian> &byteOrders,
QList<QAudioFormat::SampleType> &sampleTypes) {
frequencies.clear();
sampleSizes.clear();
byteOrders.clear();
sampleTypes.clear();
channels.clear();
for (int i=0; i<SampleRateCount; ++i)
if (caps.iRate & SampleRateListNative[i])
frequencies += SampleRateListQt[i];
for (int i=0; i<ChannelsCount; ++i)
if (caps.iChannels & ChannelsListNative[i])
channels += ChannelsListQt[i];
for (int i=0; i<EncodingCount; ++i) {
if (fourcc == EncodingFourCC[i]) {
sampleSizes += EncodingSampleSize[i];
byteOrders += EncodingByteOrder[i];
sampleTypes += EncodingSampleType[i];
}
}
}
bool formatQtToNative(const QAudioFormat &inputFormat,
TUint32 &outputFourCC,
TMMFCapabilities &outputFormat) {
bool result = false;
// Need to use temporary variables because TMMFCapabilities fields are all
// TInt, rather than MMF enumerated types.
TMMFSampleRate outputSampleRate;
TMMFMonoStereo outputChannels;
TMMFSoundEncoding outputEncoding;
if (inputFormat.codec() == QLatin1String("audio/pcm")) {
result =
sampleRateQtToNative(inputFormat.frequency(), outputSampleRate)
&& channelsQtToNative(inputFormat.channels(), outputChannels)
&& sampleInfoQtToNative(inputFormat.sampleSize(),
inputFormat.byteOrder(),
inputFormat.sampleType(),
outputFourCC,
outputEncoding);
}
if (result) {
outputFormat.iRate = outputSampleRate;
outputFormat.iChannels = outputChannels;
outputFormat.iEncoding = outputEncoding;
}
return result;
}
QAudio::State stateNativeToQt(State nativeState)
{
switch (nativeState) {
case ClosedState:
return QAudio::StoppedState;
case InitializingState:
return QAudio::StoppedState;
case ActiveState:
return QAudio::ActiveState;
case IdleState:
return QAudio::IdleState;
case SuspendedPausedState:
case SuspendedStoppedState:
return QAudio::SuspendedState;
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid state");
return QAudio::StoppedState; // suppress compiler warning
}
}
qint64 bytesToSamples(const QAudioFormat &format, qint64 length)
{
return length / ((format.sampleSize() / 8) * format.channels());
}
qint64 samplesToBytes(const QAudioFormat &format, qint64 samples)
{
return samples * (format.sampleSize() / 8) * format.channels();
}
} // namespace Utils
//-----------------------------------------------------------------------------
// DevSoundWrapper
//-----------------------------------------------------------------------------
DevSoundWrapper::DevSoundWrapper(QAudio::Mode mode, QObject *parent)
: QObject(parent)
, m_mode(mode)
, m_state(StateIdle)
, m_devsound(0)
, m_fourcc(0)
{
QT_TRAP_THROWING(m_devsound = CMMFDevSound::NewL());
switch (mode) {
case QAudio::AudioOutput:
m_nativeMode = EMMFStatePlaying;
break;
case QAudio::AudioInput:
m_nativeMode = EMMFStateRecording;
break;
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
}
getSupportedCodecs();
}
DevSoundWrapper::~DevSoundWrapper()
{
delete m_devsound;
}
const QList<QString>& DevSoundWrapper::supportedCodecs() const
{
return m_supportedCodecs;
}
void DevSoundWrapper::initialize(const QString& codec)
{
Q_ASSERT(StateInitializing != m_state);
m_state = StateInitializing;
if (QLatin1String("audio/pcm") == codec) {
m_fourcc = KMMFFourCCCodePCM16;
TRAPD(err, m_devsound->InitializeL(*this, m_fourcc, m_nativeMode));
if (KErrNone != err) {
m_state = StateIdle;
emit initializeComplete(err);
}
} else {
emit initializeComplete(KErrNotSupported);
}
}
const QList<int>& DevSoundWrapper::supportedFrequencies() const
{
Q_ASSERT(StateInitialized == m_state);
return m_supportedFrequencies;
}
const QList<int>& DevSoundWrapper::supportedChannels() const
{
Q_ASSERT(StateInitialized == m_state);
return m_supportedChannels;
}
const QList<int>& DevSoundWrapper::supportedSampleSizes() const
{
Q_ASSERT(StateInitialized == m_state);
return m_supportedSampleSizes;
}
const QList<QAudioFormat::Endian>& DevSoundWrapper::supportedByteOrders() const
{
Q_ASSERT(StateInitialized == m_state);
return m_supportedByteOrders;
}
const QList<QAudioFormat::SampleType>& DevSoundWrapper::supportedSampleTypes() const
{
Q_ASSERT(StateInitialized == m_state);
return m_supportedSampleTypes;
}
bool DevSoundWrapper::isFormatSupported(const QAudioFormat &format) const
{
Q_ASSERT(StateInitialized == m_state);
return m_supportedCodecs.contains(format.codec())
&& m_supportedFrequencies.contains(format.frequency())
&& m_supportedChannels.contains(format.channels())
&& m_supportedSampleSizes.contains(format.sampleSize())
&& m_supportedSampleTypes.contains(format.sampleType())
&& m_supportedByteOrders.contains(format.byteOrder());
}
int DevSoundWrapper::samplesProcessed() const
{
int result = 0;
if (StateInitialized == m_state) {
switch (m_mode) {
case QAudio::AudioInput:
result = m_devsound->SamplesRecorded();
break;
case QAudio::AudioOutput:
result = m_devsound->SamplesPlayed();
break;
}
}
return result;
}
bool DevSoundWrapper::setFormat(const QAudioFormat &format)
{
Q_ASSERT(StateInitialized == m_state);
bool result = false;
TUint32 fourcc;
TMMFCapabilities nativeFormat;
if (Utils::formatQtToNative(format, fourcc, nativeFormat)) {
TMMFCapabilities currentNativeFormat = m_devsound->Config();
nativeFormat.iBufferSize = currentNativeFormat.iBufferSize;
TRAPD(err, m_devsound->SetConfigL(nativeFormat));
result = (KErrNone == err);
}
return result;
}
bool DevSoundWrapper::start()
{
Q_ASSERT(StateInitialized == m_state);
int err = KErrArgument;
switch (m_mode) {
case QAudio::AudioInput:
TRAP(err, m_devsound->RecordInitL());
break;
case QAudio::AudioOutput:
TRAP(err, m_devsound->PlayInitL());
break;
}
return (KErrNone == err);
}
bool DevSoundWrapper::pause()
{
Q_ASSERT(StateInitialized == m_state);
#ifndef PRE_S60_52_PLATFORM
if (m_mode == QAudio::AudioOutput ) {
m_devsound->Pause();
return true;
} else {
const bool canPause = isResumeSupported();
if (canPause)
m_devsound->Pause();
else
stop();
return canPause;
}
#else
const bool canPause = isResumeSupported();
if (canPause)
m_devsound->Pause();
else
stop();
return canPause;
#endif
}
void DevSoundWrapper::resume()
{
Q_ASSERT(StateInitialized == m_state);
Q_ASSERT(isResumeSupported());
// TODO: QTBUG-13625
}
void DevSoundWrapper::stop()
{
m_devsound->Stop();
}
void DevSoundWrapper::bufferProcessed()
{
Q_ASSERT(StateInitialized == m_state);
switch (m_mode) {
case QAudio::AudioInput:
m_devsound->RecordData();
break;
case QAudio::AudioOutput:
m_devsound->PlayData();
break;
}
}
void DevSoundWrapper::getSupportedCodecs()
{
/*
* TODO: once we support formats other than PCM, this function should
* convert the array of FourCC codes into MIME types for each codec.
*
RArray<TFourCC> fourcc;
QT_TRAP_THROWING(CleanupClosePushL(&fourcc));
TMMFPrioritySettings settings;
switch (mode) {
case QAudio::AudioOutput:
settings.iState = EMMFStatePlaying;
m_devsound->GetSupportedInputDataTypesL(fourcc, settings);
break;
case QAudio::AudioInput:
settings.iState = EMMFStateRecording;
m_devsound->GetSupportedInputDataTypesL(fourcc, settings);
break;
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
}
CleanupStack::PopAndDestroy(); // fourcc
*/
m_supportedCodecs.append(QLatin1String("audio/pcm"));
}
void DevSoundWrapper::populateCapabilities()
{
m_supportedFrequencies.clear();
m_supportedChannels.clear();
m_supportedSampleSizes.clear();
m_supportedByteOrders.clear();
m_supportedSampleTypes.clear();
const TMMFCapabilities caps = m_devsound->Capabilities();
for (int i=0; i<Utils::SampleRateCount; ++i)
if (caps.iRate & Utils::SampleRateListNative[i])
m_supportedFrequencies += Utils::SampleRateListQt[i];
for (int i=0; i<Utils::ChannelsCount; ++i)
if (caps.iChannels & Utils::ChannelsListNative[i])
m_supportedChannels += Utils::ChannelsListQt[i];
for (int i=0; i<Utils::EncodingCount; ++i) {
if (m_fourcc == Utils::EncodingFourCC[i]) {
m_supportedSampleSizes += Utils::EncodingSampleSize[i];
m_supportedByteOrders += Utils::EncodingByteOrder[i];
m_supportedSampleTypes += Utils::EncodingSampleType[i];
}
}
}
bool DevSoundWrapper::isResumeSupported() const
{
// TODO: QTBUG-13625
return false;
}
void DevSoundWrapper::InitializeComplete(TInt aError)
{
Q_ASSERT(StateInitializing == m_state);
if (KErrNone == aError) {
m_state = StateInitialized;
populateCapabilities();
} else {
m_state = StateIdle;
}
emit initializeComplete(aError);
}
void DevSoundWrapper::ToneFinished(TInt aError)
{
Q_UNUSED(aError)
// This class doesn't use DevSound's tone playback functions, so should
// never receive this callback.
Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback");
}
void DevSoundWrapper::BufferToBeFilled(CMMFBuffer *aBuffer)
{
Q_ASSERT(QAudio::AudioOutput == m_mode);
emit bufferToBeProcessed(aBuffer);
}
void DevSoundWrapper::PlayError(TInt aError)
{
Q_ASSERT(QAudio::AudioOutput == m_mode);
emit processingError(aError);
}
void DevSoundWrapper::BufferToBeEmptied(CMMFBuffer *aBuffer)
{
Q_ASSERT(QAudio::AudioInput == m_mode);
emit bufferToBeProcessed(aBuffer);
}
void DevSoundWrapper::RecordError(TInt aError)
{
Q_ASSERT(QAudio::AudioInput == m_mode);
emit processingError(aError);
}
void DevSoundWrapper::ConvertError(TInt aError)
{
Q_UNUSED(aError)
// This class doesn't use DevSound's format conversion functions, so
// should never receive this callback.
Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback");
}
void DevSoundWrapper::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg)
{
Q_UNUSED(aMessageType)
Q_UNUSED(aMsg)
// Ignore this callback.
}
#ifndef PRE_S60_52_PLATFORM
int DevSoundWrapper::flush()
{
return m_devsound->EmptyBuffers();
}
#endif
} // namespace SymbianAudio
QT_END_NAMESPACE

View File

@@ -0,0 +1,204 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIO_SYMBIAN_P_H
#define QAUDIO_SYMBIAN_P_H
#include <QtCore/qnamespace.h>
#include <QtCore/QList>
#include <QtCore/QString>
#include <qaudioformat.h>
#include <qaudio.h>
#include <sounddevice.h>
QT_BEGIN_NAMESPACE
namespace SymbianAudio {
/**
* Default values used by audio input and output classes, when underlying
* DevSound instance has not yet been created.
*/
const int DefaultBufferSize = 4096; // bytes
const int DefaultNotifyInterval = 1000; // ms
/**
* Enumeration used to track state of internal DevSound instances.
* Values are translated to the corresponding QAudio::State values by
* SymbianAudio::Utils::stateNativeToQt.
*/
enum State {
ClosedState
, InitializingState
, ActiveState
, IdleState
// QAudio is suspended; DevSound is paused
, SuspendedPausedState
// QAudio is suspended; DevSound is stopped
, SuspendedStoppedState
};
/**
* Wrapper around DevSound instance
*/
class DevSoundWrapper
: public QObject
, public MDevSoundObserver
{
Q_OBJECT
public:
DevSoundWrapper(QAudio::Mode mode, QObject *parent = 0);
~DevSoundWrapper();
public:
// List of supported codecs; can be called once object is constructed
const QList<QString>& supportedCodecs() const;
// Asynchronous initialization function; emits devsoundInitializeComplete
void initialize(const QString& codec);
// Capabilities, for selected codec. Can be called once initialize has returned
// successfully.
const QList<int>& supportedFrequencies() const;
const QList<int>& supportedChannels() const;
const QList<int>& supportedSampleSizes() const;
const QList<QAudioFormat::Endian>& supportedByteOrders() const;
const QList<QAudioFormat::SampleType>& supportedSampleTypes() const;
bool isFormatSupported(const QAudioFormat &format) const;
int samplesProcessed() const;
bool setFormat(const QAudioFormat &format);
bool start();
// If DevSound implementation supports pause, calls pause and returns true.
// Otherwise calls stop and returns false. In this case, all DevSound buffers
// currently held by the backend must be discarded.
bool pause();
void resume();
void stop();
void bufferProcessed();
#ifndef PRE_S60_52_PLATFORM
int flush();
#endif
public:
// MDevSoundObserver
void InitializeComplete(TInt aError);
void ToneFinished(TInt aError);
void BufferToBeFilled(CMMFBuffer *aBuffer);
void PlayError(TInt aError);
void BufferToBeEmptied(CMMFBuffer *aBuffer);
void RecordError(TInt aError);
void ConvertError(TInt aError);
void DeviceMessage(TUid aMessageType, const TDesC8 &aMsg);
signals:
void initializeComplete(int error);
void bufferToBeProcessed(CMMFBuffer *buffer);
void processingError(int error);
private:
void getSupportedCodecs();
void populateCapabilities();
bool isResumeSupported() const;
private:
const QAudio::Mode m_mode;
TMMFState m_nativeMode;
enum State {
StateIdle,
StateInitializing,
StateInitialized
} m_state;
CMMFDevSound* m_devsound;
TFourCC m_fourcc;
QList<QString> m_supportedCodecs;
QList<int> m_supportedFrequencies;
QList<int> m_supportedChannels;
QList<int> m_supportedSampleSizes;
QList<QAudioFormat::Endian> m_supportedByteOrders;
QList<QAudioFormat::SampleType> m_supportedSampleTypes;
};
namespace Utils {
/**
* Convert internal states to QAudio states.
*/
QAudio::State stateNativeToQt(State nativeState);
/**
* Convert data length to number of samples.
*/
qint64 bytesToSamples(const QAudioFormat &format, qint64 length);
/**
* Convert number of samples to data length.
*/
qint64 samplesToBytes(const QAudioFormat &format, qint64 samples);
} // namespace Utils
} // namespace SymbianAudio
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,292 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include "qaudiosystem.h"
#include "qaudiosystemplugin.h"
#include "qaudiopluginloader_p.h"
#include "qaudiodevicefactory_p.h"
#ifndef QT_NO_AUDIO_BACKEND
#if defined(Q_OS_WIN)
#include "qaudiodeviceinfo_win32_p.h"
#include "qaudiooutput_win32_p.h"
#include "qaudioinput_win32_p.h"
#elif defined(Q_OS_MAC)
#include "qaudiodeviceinfo_mac_p.h"
#include "qaudiooutput_mac_p.h"
#include "qaudioinput_mac_p.h"
#elif defined(HAS_ALSA)
#include "qaudiodeviceinfo_alsa_p.h"
#include "qaudiooutput_alsa_p.h"
#include "qaudioinput_alsa_p.h"
#elif defined(Q_OS_SYMBIAN)
#include "qaudiodeviceinfo_symbian_p.h"
#include "qaudiooutput_symbian_p.h"
#include "qaudioinput_symbian_p.h"
#endif
#endif
QT_BEGIN_NAMESPACE
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
Q_GLOBAL_STATIC_WITH_ARGS(QAudioPluginLoader, audioLoader,
(QAudioSystemFactoryInterface_iid, QLatin1String("/audio"), Qt::CaseInsensitive))
#endif
class QNullDeviceInfo : public QAbstractAudioDeviceInfo
{
public:
QAudioFormat preferredFormat() const { qWarning()<<"using null deviceinfo, none available"; return QAudioFormat(); }
bool isFormatSupported(const QAudioFormat& ) const { return false; }
QAudioFormat nearestFormat(const QAudioFormat& ) const { return QAudioFormat(); }
QString deviceName() const { return QString(); }
QStringList supportedCodecs() { return QStringList(); }
QList<int> supportedSampleRates() { return QList<int>(); }
QList<int> supportedChannelCounts() { return QList<int>(); }
QList<int> supportedSampleSizes() { return QList<int>(); }
QList<QAudioFormat::Endian> supportedByteOrders() { return QList<QAudioFormat::Endian>(); }
QList<QAudioFormat::SampleType> supportedSampleTypes() { return QList<QAudioFormat::SampleType>(); }
};
class QNullInputDevice : public QAbstractAudioInput
{
public:
void start(QIODevice*) { qWarning()<<"using null input device, none available";}
QIODevice* start() { qWarning()<<"using null input device, none available"; return 0; }
void stop() {}
void reset() {}
void suspend() {}
void resume() {}
int bytesReady() const { return 0; }
int periodSize() const { return 0; }
void setBufferSize(int ) {}
int bufferSize() const { return 0; }
void setNotifyInterval(int ) {}
int notifyInterval() const { return 0; }
qint64 processedUSecs() const { return 0; }
qint64 elapsedUSecs() const { return 0; }
QAudio::Error error() const { return QAudio::OpenError; }
QAudio::State state() const { return QAudio::StoppedState; }
void setFormat(const QAudioFormat&) {}
QAudioFormat format() const { return QAudioFormat(); }
};
class QNullOutputDevice : public QAbstractAudioOutput
{
public:
void start(QIODevice*) {qWarning()<<"using null output device, none available";}
QIODevice* start() { qWarning()<<"using null output device, none available"; return 0; }
void stop() {}
void reset() {}
void suspend() {}
void resume() {}
int bytesFree() const { return 0; }
int periodSize() const { return 0; }
void setBufferSize(int ) {}
int bufferSize() const { return 0; }
void setNotifyInterval(int ) {}
int notifyInterval() const { return 0; }
qint64 processedUSecs() const { return 0; }
qint64 elapsedUSecs() const { return 0; }
QAudio::Error error() const { return QAudio::OpenError; }
QAudio::State state() const { return QAudio::StoppedState; }
void setFormat(const QAudioFormat&) {}
QAudioFormat format() const { return QAudioFormat(); }
};
QList<QAudioDeviceInfo> QAudioDeviceFactory::availableDevices(QAudio::Mode mode)
{
QList<QAudioDeviceInfo> devices;
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN))
foreach (const QByteArray &handle, QAudioDeviceInfoInternal::availableDevices(mode))
devices << QAudioDeviceInfo(QLatin1String("builtin"), handle, mode);
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioPluginLoader* l = audioLoader();
foreach (const QString& key, l->keys()) {
QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(l->instance(key));
if (plugin) {
foreach (QByteArray const& handle, plugin->availableDevices(mode))
devices << QAudioDeviceInfo(key, handle, mode);
}
delete plugin;
}
#endif
return devices;
}
QAudioDeviceInfo QAudioDeviceFactory::defaultInputDevice()
{
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(QLatin1String("default")));
if (plugin) {
QList<QByteArray> list = plugin->availableDevices(QAudio::AudioInput);
if (list.size() > 0)
return QAudioDeviceInfo(QLatin1String("default"), list.at(0), QAudio::AudioInput);
}
#endif
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN))
return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultInputDevice(), QAudio::AudioInput);
#endif
#endif
return QAudioDeviceInfo();
}
QAudioDeviceInfo QAudioDeviceFactory::defaultOutputDevice()
{
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(QLatin1String("default")));
if (plugin) {
QList<QByteArray> list = plugin->availableDevices(QAudio::AudioOutput);
if (list.size() > 0)
return QAudioDeviceInfo(QLatin1String("default"), list.at(0), QAudio::AudioOutput);
}
#endif
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN))
return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultOutputDevice(), QAudio::AudioOutput);
#endif
#endif
return QAudioDeviceInfo();
}
QAbstractAudioDeviceInfo* QAudioDeviceFactory::audioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode)
{
QAbstractAudioDeviceInfo *rc = 0;
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN))
if (realm == QLatin1String("builtin"))
return new QAudioDeviceInfoInternal(handle, mode);
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin =
qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(realm));
if (plugin)
rc = plugin->createDeviceInfo(handle, mode);
#endif
return rc == 0 ? new QNullDeviceInfo() : rc;
}
QAbstractAudioInput* QAudioDeviceFactory::createDefaultInputDevice(QAudioFormat const &format)
{
return createInputDevice(defaultInputDevice(), format);
}
QAbstractAudioOutput* QAudioDeviceFactory::createDefaultOutputDevice(QAudioFormat const &format)
{
return createOutputDevice(defaultOutputDevice(), format);
}
QAbstractAudioInput* QAudioDeviceFactory::createInputDevice(QAudioDeviceInfo const& deviceInfo, QAudioFormat const &format)
{
if (deviceInfo.isNull())
return new QNullInputDevice();
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN))
if (deviceInfo.realm() == QLatin1String("builtin")) {
QAbstractAudioInput* p = new QAudioInputPrivate(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin =
qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(deviceInfo.realm()));
if (plugin) {
QAbstractAudioInput* p = plugin->createInput(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
return new QNullInputDevice();
}
QAbstractAudioOutput* QAudioDeviceFactory::createOutputDevice(QAudioDeviceInfo const& deviceInfo, QAudioFormat const &format)
{
if (deviceInfo.isNull())
return new QNullOutputDevice();
#ifndef QT_NO_AUDIO_BACKEND
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN))
if (deviceInfo.realm() == QLatin1String("builtin")) {
QAbstractAudioOutput* p = new QAudioOutputPrivate(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
#endif
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
QAudioSystemFactoryInterface* plugin =
qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(deviceInfo.realm()));
if (plugin) {
QAbstractAudioOutput* p = plugin->createOutput(deviceInfo.handle());
if (p) p->setFormat(format);
return p;
}
#endif
return new QNullOutputDevice();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEFACTORY_P_H
#define QAUDIODEVICEFACTORY_P_H
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include "qaudiodeviceinfo.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QAbstractAudioInput;
class QAbstractAudioOutput;
class QAbstractAudioDeviceInfo;
class QAudioDeviceFactory
{
public:
static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode);
static QAudioDeviceInfo defaultInputDevice();
static QAudioDeviceInfo defaultOutputDevice();
static QAbstractAudioDeviceInfo* audioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode);
static QAbstractAudioInput* createDefaultInputDevice(QAudioFormat const &format);
static QAbstractAudioOutput* createDefaultOutputDevice(QAudioFormat const &format);
static QAbstractAudioInput* createInputDevice(QAudioDeviceInfo const &device, QAudioFormat const &format);
static QAbstractAudioOutput* createOutputDevice(QAudioDeviceInfo const &device, QAudioFormat const &format);
static QAbstractAudioInput* createNullInput();
static QAbstractAudioOutput* createNullOutput();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIODEVICEFACTORY_P_H

View File

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

View File

@@ -0,0 +1,113 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIODEVICEINFO_H
#define QAUDIODEVICEINFO_H
#include <QtCore/qobject.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include <qaudio.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QAudioDeviceFactory;
class QAudioDeviceInfoPrivate;
class Q_MULTIMEDIA_EXPORT QAudioDeviceInfo
{
friend class QAudioDeviceFactory;
public:
QAudioDeviceInfo();
QAudioDeviceInfo(const QAudioDeviceInfo& other);
~QAudioDeviceInfo();
QAudioDeviceInfo& operator=(const QAudioDeviceInfo& other);
bool isNull() const;
QString deviceName() const;
bool isFormatSupported(const QAudioFormat &format) const;
QAudioFormat preferredFormat() const;
QAudioFormat nearestFormat(const QAudioFormat &format) const;
QStringList supportedCodecs() const;
QList<int> supportedFrequencies() const;
QList<int> supportedSampleRates() const;
QList<int> supportedChannels() const;
QList<int> supportedChannelCounts() const;
QList<int> supportedSampleSizes() const;
QList<QAudioFormat::Endian> supportedByteOrders() const;
QList<QAudioFormat::SampleType> supportedSampleTypes() const;
static QAudioDeviceInfo defaultInputDevice();
static QAudioDeviceInfo defaultOutputDevice();
static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode);
private:
QAudioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode);
QString realm() const;
QByteArray handle() const;
QAudio::Mode mode() const;
QSharedDataPointer<QAudioDeviceInfoPrivate> d;
};
QT_END_NAMESPACE
QT_END_HEADER
Q_DECLARE_METATYPE(QAudioDeviceInfo)
#endif // QAUDIODEVICEINFO_H

View File

@@ -0,0 +1,535 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qaudiodeviceinfo_alsa_p.h"
#include <alsa/version.h>
QT_BEGIN_NAMESPACE
QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray dev, QAudio::Mode mode)
{
handle = 0;
device = QLatin1String(dev);
this->mode = mode;
checkSurround();
}
QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
{
close();
}
bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
return testSettings(format);
}
QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
QAudioFormat nearest;
if(mode == QAudio::AudioOutput) {
nearest.setFrequency(44100);
nearest.setChannels(2);
nearest.setByteOrder(QAudioFormat::LittleEndian);
nearest.setSampleType(QAudioFormat::SignedInt);
nearest.setSampleSize(16);
nearest.setCodec(QLatin1String("audio/pcm"));
} else {
nearest.setFrequency(8000);
nearest.setChannels(1);
nearest.setSampleType(QAudioFormat::UnSignedInt);
nearest.setSampleSize(8);
nearest.setCodec(QLatin1String("audio/pcm"));
if(!testSettings(nearest)) {
nearest.setChannels(2);
nearest.setSampleSize(16);
nearest.setSampleType(QAudioFormat::SignedInt);
}
}
return nearest;
}
QString QAudioDeviceInfoInternal::deviceName() const
{
return device;
}
QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
updateLists();
return codecz;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
updateLists();
return freqz;
}
QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
updateLists();
return channelz;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
updateLists();
return sizez;
}
QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
updateLists();
return byteOrderz;
}
QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
updateLists();
return typez;
}
bool QAudioDeviceInfoInternal::open()
{
int err = 0;
QString dev = device;
QList<QByteArray> devices = availableDevices(mode);
if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
if (devices.size() > 0)
dev = QLatin1String(devices.first().constData());
else
return false;
#else
dev = QLatin1String("hw:0,0");
#endif
} else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = device;
#else
int idx = 0;
char *name;
QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);
while(snd_card_get_name(idx,&name) == 0) {
if(dev.contains(QLatin1String(name)))
break;
idx++;
}
dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
}
if(mode == QAudio::AudioOutput) {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
} else {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
}
if(err < 0) {
handle = 0;
return false;
}
return true;
}
void QAudioDeviceInfoInternal::close()
{
if(handle)
snd_pcm_close(handle);
handle = 0;
}
bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
{
// Set nearest to closest settings that do work.
// See if what is in settings will work (return value).
int err = 0;
snd_pcm_t* handle;
snd_pcm_hw_params_t *params;
QString dev = device;
QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
if(dev.compare(QLatin1String("default")) == 0) {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = QLatin1String(devices.first().constData());
#else
dev = QLatin1String("hw:0,0");
#endif
} else {
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
dev = device;
#else
int idx = 0;
char *name;
QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);
while(snd_card_get_name(idx,&name) == 0) {
if(shortName.compare(QLatin1String(name)) == 0)
break;
idx++;
}
dev = QString(QLatin1String("hw:%1,0")).arg(idx);
#endif
}
if(mode == QAudio::AudioOutput) {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
} else {
err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
}
if(err < 0) {
handle = 0;
return false;
}
bool testChannel = false;
bool testCodec = false;
bool testFreq = false;
bool testType = false;
bool testSize = false;
int dir = 0;
snd_pcm_nonblock( handle, 0 );
snd_pcm_hw_params_alloca( &params );
snd_pcm_hw_params_any( handle, params );
// set the values!
snd_pcm_hw_params_set_channels(handle,params,format.channels());
snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
err = -1;
switch(format.sampleSize()) {
case 8:
if(format.sampleType() == QAudioFormat::SignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
else if(format.sampleType() == QAudioFormat::UnSignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
break;
case 16:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
}
break;
case 32:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
}
}
// For now, just accept only audio/pcm codec
if(!format.codec().startsWith(QLatin1String("audio/pcm"))) {
err=-1;
} else
testCodec = true;
if(err>=0 && format.channels() != -1) {
err = snd_pcm_hw_params_test_channels(handle,params,format.channels());
if(err>=0)
err = snd_pcm_hw_params_set_channels(handle,params,format.channels());
if(err>=0)
testChannel = true;
}
if(err>=0 && format.frequency() != -1) {
err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0);
if(err>=0)
err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
if(err>=0)
testFreq = true;
}
if((err>=0 && format.sampleSize() != -1) &&
(format.sampleType() != QAudioFormat::Unknown)) {
switch(format.sampleSize()) {
case 8:
if(format.sampleType() == QAudioFormat::SignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
else if(format.sampleType() == QAudioFormat::UnSignedInt)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
break;
case 16:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
}
break;
case 32:
if(format.sampleType() == QAudioFormat::SignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
if(format.byteOrder() == QAudioFormat::LittleEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
else if(format.byteOrder() == QAudioFormat::BigEndian)
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
}
}
if(err>=0) {
testSize = true;
testType = true;
}
}
if(err>=0)
err = snd_pcm_hw_params(handle, params);
if(err == 0) {
// settings work
// close()
if(handle)
snd_pcm_close(handle);
return true;
}
if(handle)
snd_pcm_close(handle);
return false;
}
void QAudioDeviceInfoInternal::updateLists()
{
// redo all lists based on current settings
freqz.clear();
channelz.clear();
sizez.clear();
byteOrderz.clear();
typez.clear();
codecz.clear();
if(!handle)
open();
if(!handle)
return;
for(int i=0; i<(int)MAX_SAMPLE_RATES; i++) {
//if(snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0)
freqz.append(SAMPLE_RATES[i]);
}
channelz.append(1);
channelz.append(2);
if (surround40) channelz.append(4);
if (surround51) channelz.append(6);
if (surround71) channelz.append(8);
sizez.append(8);
sizez.append(16);
sizez.append(32);
byteOrderz.append(QAudioFormat::LittleEndian);
byteOrderz.append(QAudioFormat::BigEndian);
typez.append(QAudioFormat::SignedInt);
typez.append(QAudioFormat::UnSignedInt);
typez.append(QAudioFormat::Float);
codecz.append(QLatin1String("audio/pcm"));
close();
}
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
QList<QByteArray> allDevices;
QList<QByteArray> devices;
QByteArray filter;
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
// Create a list of all current audio devices that support mode
void **hints, **n;
char *name, *descr, *io;
if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
qWarning() << "no alsa devices available";
return devices;
}
n = hints;
if(mode == QAudio::AudioInput) {
filter = "Input";
} else {
filter = "Output";
}
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
if (name != 0 && qstrcmp(name, "null") != 0) {
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if ((descr != NULL) && ((io == NULL) || (io == filter))) {
QString deviceName = QLatin1String(name);
QString deviceDescription = QLatin1String(descr);
allDevices.append(deviceName.toLocal8Bit().constData());
if (deviceDescription.contains(QLatin1String("Default Audio Device")))
devices.append(deviceName.toLocal8Bit().constData());
}
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
}
++n;
}
snd_device_name_free_hint(hints);
if(devices.size() > 0) {
devices.append("default");
}
#else
int idx = 0;
char* name;
while(snd_card_get_name(idx,&name) == 0) {
devices.append(name);
idx++;
}
if (idx > 0)
devices.append("default");
#endif
#if (!defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6))
if (devices.size() == 0 && allDevices.size() > 0)
return allDevices;
#endif
return devices;
}
QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
QList<QByteArray> devices = availableDevices(QAudio::AudioInput);
if(devices.size() == 0)
return QByteArray();
return devices.first();
}
QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
QList<QByteArray> devices = availableDevices(QAudio::AudioOutput);
if(devices.size() == 0)
return QByteArray();
return devices.first();
}
void QAudioDeviceInfoInternal::checkSurround()
{
QList<QByteArray> devices;
surround40 = false;
surround51 = false;
surround71 = false;
void **hints, **n;
char *name, *descr, *io;
if(snd_device_name_hint(-1, "pcm", &hints) < 0)
return;
n = hints;
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if((name != NULL) && (descr != NULL)) {
QString deviceName = QLatin1String(name);
if (mode == QAudio::AudioOutput) {
if(deviceName.contains(QLatin1String("surround40")))
surround40 = true;
if(deviceName.contains(QLatin1String("surround51")))
surround51 = true;
if(deviceName.contains(QLatin1String("surround71")))
surround71 = true;
}
}
if(name != NULL)
free(name);
if(descr != NULL)
free(descr);
if(io != NULL)
free(io);
++n;
}
snd_device_name_free_hint(hints);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,121 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEINFOALSA_H
#define QAUDIODEVICEINFOALSA_H
#include <alsa/asoundlib.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <QtCore/qdebug.h>
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_NAMESPACE
const unsigned int MAX_SAMPLE_RATES = 5;
const unsigned int SAMPLE_RATES[] =
{ 8000, 11025, 22050, 44100, 48000 };
class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo
{
Q_OBJECT
public:
QAudioDeviceInfoInternal(QByteArray dev,QAudio::Mode mode);
~QAudioDeviceInfoInternal();
bool testSettings(const QAudioFormat& format) const;
void updateLists();
QAudioFormat preferredFormat() const;
bool isFormatSupported(const QAudioFormat& format) const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode);
private:
bool open();
void close();
void checkSurround();
bool surround40;
bool surround51;
bool surround71;
QString device;
QAudio::Mode mode;
QAudioFormat nearest;
QList<int> freqz;
QList<int> channelz;
QList<int> sizez;
QList<QAudioFormat::Endian> byteOrderz;
QStringList codecz;
QList<QAudioFormat::SampleType> typez;
snd_pcm_t* handle;
snd_pcm_hw_params_t *params;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,351 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qdebug.h>
#include <qaudiodeviceinfo.h>
#include "qaudio_mac_p.h"
#include "qaudiodeviceinfo_mac_p.h"
QT_BEGIN_NAMESPACE
// XXX: remove at some future date
static inline QString cfStringToQString(CFStringRef str)
{
CFIndex length = CFStringGetLength(str);
const UniChar *chars = CFStringGetCharactersPtr(str);
if (chars)
return QString(reinterpret_cast<const QChar *>(chars), length);
UniChar buffer[length];
CFStringGetCharacters(str, CFRangeMake(0, length), buffer);
return QString(reinterpret_cast<const QChar *>(buffer), length);
}
QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray const& handle, QAudio::Mode)
{
QDataStream ds(handle);
quint32 did, tm;
ds >> did >> tm >> name;
deviceId = AudioDeviceID(did);
mode = QAudio::Mode(tm);
}
bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
{
QAudioDeviceInfoInternal *self = const_cast<QAudioDeviceInfoInternal*>(this);
return format.isValid()
&& format.codec() == QString::fromLatin1("audio/pcm")
&& self->supportedSampleRates().contains(format.sampleRate())
&& self->supportedChannelCounts().contains(format.channelCount())
&& self->supportedSampleSizes().contains(format.sampleSize());
}
QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
QAudioFormat rc;
UInt32 propSize = 0;
if (AudioDeviceGetPropertyInfo(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreams,
&propSize,
0) == noErr) {
const int sc = propSize / sizeof(AudioStreamID);
if (sc > 0) {
AudioStreamID* streams = new AudioStreamID[sc];
if (AudioDeviceGetProperty(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreams,
&propSize,
streams) == noErr) {
for (int i = 0; i < sc; ++i) {
if (AudioStreamGetPropertyInfo(streams[i],
0,
kAudioStreamPropertyPhysicalFormat,
&propSize,
0) == noErr) {
AudioStreamBasicDescription sf;
if (AudioStreamGetProperty(streams[i],
0,
kAudioStreamPropertyPhysicalFormat,
&propSize,
&sf) == noErr) {
rc = toQAudioFormat(sf);
break;
}
}
}
}
delete streams;
}
}
return rc;
}
QString QAudioDeviceInfoInternal::deviceName() const
{
return name;
}
QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
return QStringList() << QString::fromLatin1("audio/pcm");
}
QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
QSet<int> rc;
// Add some common frequencies
rc << 8000 << 11025 << 22050 << 44100;
//
UInt32 propSize = 0;
if (AudioDeviceGetPropertyInfo(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyAvailableNominalSampleRates,
&propSize,
0) == noErr) {
const int pc = propSize / sizeof(AudioValueRange);
if (pc > 0) {
AudioValueRange* vr = new AudioValueRange[pc];
if (AudioDeviceGetProperty(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyAvailableNominalSampleRates,
&propSize,
vr) == noErr) {
for (int i = 0; i < pc; ++i)
rc << vr[i].mMaximum;
}
delete vr;
}
}
return rc.toList();
}
QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
QList<int> rc;
// Can mix down to 1 channel
rc << 1;
UInt32 propSize = 0;
int channels = 0;
if (AudioDeviceGetPropertyInfo(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreamConfiguration,
&propSize,
0) == noErr) {
AudioBufferList* audioBufferList = static_cast<AudioBufferList*>(qMalloc(propSize));
if (audioBufferList != 0) {
if (AudioDeviceGetProperty(deviceId,
0,
mode == QAudio::AudioInput,
kAudioDevicePropertyStreamConfiguration,
&propSize,
audioBufferList) == noErr) {
for (int i = 0; i < int(audioBufferList->mNumberBuffers); ++i) {
channels += audioBufferList->mBuffers[i].mNumberChannels;
rc << channels;
}
}
qFree(audioBufferList);
}
}
return rc;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
return QList<int>() << 8 << 16 << 24 << 32 << 64;
}
QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian;
}
QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
}
static QByteArray get_device_info(AudioDeviceID audioDevice, QAudio::Mode mode)
{
UInt32 size;
QByteArray device;
QDataStream ds(&device, QIODevice::WriteOnly);
AudioStreamBasicDescription sf;
CFStringRef name;
Boolean isInput = mode == QAudio::AudioInput;
// Id
ds << quint32(audioDevice);
// Mode
size = sizeof(AudioStreamBasicDescription);
if (AudioDeviceGetProperty(audioDevice, 0, isInput, kAudioDevicePropertyStreamFormat,
&size, &sf) != noErr) {
return QByteArray();
}
ds << quint32(mode);
// Name
size = sizeof(CFStringRef);
if (AudioDeviceGetProperty(audioDevice, 0, isInput, kAudioObjectPropertyName,
&size, &name) != noErr) {
qWarning() << "QAudioDeviceInfo: Unable to find device name";
return QByteArray();
}
ds << cfStringToQString(name);
CFRelease(name);
return device;
}
QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
AudioDeviceID audioDevice;
UInt32 size = sizeof(audioDevice);
if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &size,
&audioDevice) != noErr) {
qWarning() << "QAudioDeviceInfo: Unable to find default input device";
return QByteArray();
}
return get_device_info(audioDevice, QAudio::AudioInput);
}
QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
AudioDeviceID audioDevice;
UInt32 size = sizeof(audioDevice);
if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size,
&audioDevice) != noErr) {
qWarning() << "QAudioDeviceInfo: Unable to find default output device";
return QByteArray();
}
return get_device_info(audioDevice, QAudio::AudioOutput);
}
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
{
QList<QByteArray> devices;
UInt32 propSize = 0;
if (AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &propSize, 0) == noErr) {
const int dc = propSize / sizeof(AudioDeviceID);
if (dc > 0) {
AudioDeviceID* audioDevices = new AudioDeviceID[dc];
if (AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &propSize, audioDevices) == noErr) {
for (int i = 0; i < dc; ++i) {
QByteArray info = get_device_info(audioDevices[i], mode);
if (!info.isNull())
devices << info;
}
}
delete audioDevices;
}
}
return devices;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QDEVICEINFO_MAC_P_H
#define QDEVICEINFO_MAC_P_H
#include <CoreAudio/CoreAudio.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo
{
public:
AudioDeviceID deviceId;
QString name;
QAudio::Mode mode;
QAudioDeviceInfoInternal(QByteArray const& handle, QAudio::Mode mode);
bool isFormatSupported(const QAudioFormat& format) const;
QAudioFormat preferredFormat() const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode mode);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QDEVICEINFO_MAC_P_H

View File

@@ -0,0 +1,235 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QCoreApplication>
#include "qaudiodeviceinfo_symbian_p.h"
#include "qaudio_symbian_p.h"
QT_BEGIN_NAMESPACE
QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray device,
QAudio::Mode mode)
: m_deviceName(QLatin1String(device))
, m_mode(mode)
, m_updated(false)
{
}
QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
{
}
QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
{
QAudioFormat format;
switch (m_mode) {
case QAudio::AudioOutput:
format.setFrequency(44100);
format.setChannels(2);
format.setSampleSize(16);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
format.setCodec(QLatin1String("audio/pcm"));
break;
case QAudio::AudioInput:
format.setFrequency(8000);
format.setChannels(1);
format.setSampleSize(16);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
format.setCodec(QLatin1String("audio/pcm"));
break;
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
}
if (!isFormatSupported(format)) {
format = QAudioFormat();
format.setCodec(QLatin1String("audio/pcm"));
if (m_capabilities.contains(format.codec())) {
const Capabilities &codecCaps = m_capabilities[format.codec()];
if (codecCaps.m_frequencies.size())
format.setFrequency(codecCaps.m_frequencies[0]);
if (codecCaps.m_channels.size())
format.setChannels(codecCaps.m_channels[0]);
if (codecCaps.m_sampleSizes.size())
format.setSampleSize(codecCaps.m_sampleSizes[0]);
if (codecCaps.m_byteOrders.size())
format.setByteOrder(codecCaps.m_byteOrders[0]);
if (codecCaps.m_sampleTypes.size())
format.setSampleType(codecCaps.m_sampleTypes[0]);
}
}
return format;
}
bool QAudioDeviceInfoInternal::isFormatSupported(
const QAudioFormat &format) const
{
getSupportedFormats();
bool supported = false;
if (m_capabilities.contains(format.codec())) {
const Capabilities &codecCaps = m_capabilities[format.codec()];
supported = codecCaps.m_frequencies.contains(format.frequency())
&& codecCaps.m_channels.contains(format.channels())
&& codecCaps.m_sampleSizes.contains(format.sampleSize())
&& codecCaps.m_byteOrders.contains(format.byteOrder())
&& codecCaps.m_sampleTypes.contains(format.sampleType());
}
return supported;
}
QString QAudioDeviceInfoInternal::deviceName() const
{
return m_deviceName;
}
QStringList QAudioDeviceInfoInternal::supportedCodecs()
{
getSupportedFormats();
return m_capabilities.keys();
}
QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
{
getSupportedFormats();
return m_unionCapabilities.m_frequencies;
}
QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
{
getSupportedFormats();
return m_unionCapabilities.m_channels;
}
QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
{
getSupportedFormats();
return m_unionCapabilities.m_sampleSizes;
}
QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
{
getSupportedFormats();
return m_unionCapabilities.m_byteOrders;
}
QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
{
getSupportedFormats();
return m_unionCapabilities. m_sampleTypes;
}
QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
{
return QByteArray("default");
}
QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
{
return QByteArray("default");
}
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode)
{
QList<QByteArray> result;
result += QByteArray("default");
return result;
}
void QAudioDeviceInfoInternal::devsoundInitializeComplete(int err)
{
m_intializationResult = err;
m_initializing = false;
}
// Helper function
template<typename T>
void appendUnique(QList<T> &left, const QList<T> &right)
{
foreach (const T &value, right)
if (!left.contains(value))
left += value;
}
void QAudioDeviceInfoInternal::getSupportedFormats() const
{
if (!m_updated) {
QScopedPointer<SymbianAudio::DevSoundWrapper> devsound(new SymbianAudio::DevSoundWrapper(m_mode));
connect(devsound.data(), SIGNAL(initializeComplete(int)),
this, SLOT(devsoundInitializeComplete(int)));
foreach (const QString& codec, devsound->supportedCodecs()) {
m_initializing = true;
devsound->initialize(codec);
while (m_initializing)
QCoreApplication::instance()->processEvents(QEventLoop::WaitForMoreEvents);
if (KErrNone == m_intializationResult) {
m_capabilities[codec].m_frequencies = devsound->supportedFrequencies();
appendUnique(m_unionCapabilities.m_frequencies, devsound->supportedFrequencies());
m_capabilities[codec].m_channels = devsound->supportedChannels();
appendUnique(m_unionCapabilities.m_channels, devsound->supportedChannels());
m_capabilities[codec].m_sampleSizes = devsound->supportedSampleSizes();
appendUnique(m_unionCapabilities.m_sampleSizes, devsound->supportedSampleSizes());
m_capabilities[codec].m_byteOrders = devsound->supportedByteOrders();
appendUnique(m_unionCapabilities.m_byteOrders, devsound->supportedByteOrders());
m_capabilities[codec].m_sampleTypes = devsound->supportedSampleTypes();
appendUnique(m_unionCapabilities.m_sampleTypes, devsound->supportedSampleTypes());
}
}
m_updated = true;
}
}
QT_END_NAMESPACE
#include "moc_qaudiodeviceinfo_symbian_p.cpp"

View File

@@ -0,0 +1,116 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEINFO_SYMBIAN_P_H
#define QAUDIODEVICEINFO_SYMBIAN_P_H
#include <QtCore/QMap>
#include <qaudiosystem.h>
#include <sounddevice.h>
QT_BEGIN_NAMESPACE
class QAudioDeviceInfoInternal
: public QAbstractAudioDeviceInfo
{
Q_OBJECT
public:
QAudioDeviceInfoInternal(QByteArray device, QAudio::Mode mode);
~QAudioDeviceInfoInternal();
// QAbstractAudioDeviceInfo
QAudioFormat preferredFormat() const;
bool isFormatSupported(const QAudioFormat &format) const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode);
private slots:
void devsoundInitializeComplete(int err);
private:
void getSupportedFormats() const;
private:
mutable bool m_initializing;
int m_intializationResult;
QString m_deviceName;
QAudio::Mode m_mode;
struct Capabilities
{
QList<int> m_frequencies;
QList<int> m_channels;
QList<int> m_sampleSizes;
QList<QAudioFormat::Endian> m_byteOrders;
QList<QAudioFormat::SampleType> m_sampleTypes;
};
// Mutable to allow lazy initialization when called from const-qualified
// public functions (isFormatSupported, nearestFormat)
mutable bool m_updated;
mutable QMap<QString, Capabilities> m_capabilities;
mutable Capabilities m_unionCapabilities;
};
QT_END_NAMESPACE
#endif

View File

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

View File

@@ -0,0 +1,112 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIODEVICEINFOWIN_H
#define QAUDIODEVICEINFOWIN_H
#include <QtCore/qbytearray.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>
#include <QtCore/qdebug.h>
#include <qaudiodeviceinfo.h>
#include <qaudiosystem.h>
QT_BEGIN_NAMESPACE
const unsigned int MAX_SAMPLE_RATES = 5;
const unsigned int SAMPLE_RATES[] = { 8000, 11025, 22050, 44100, 48000 };
class QAudioDeviceInfoInternal : public QAbstractAudioDeviceInfo
{
Q_OBJECT
public:
QAudioDeviceInfoInternal(QByteArray dev,QAudio::Mode mode);
~QAudioDeviceInfoInternal();
bool open();
void close();
bool testSettings(const QAudioFormat& format) const;
void updateLists();
QAudioFormat preferredFormat() const;
bool isFormatSupported(const QAudioFormat& format) const;
QString deviceName() const;
QStringList supportedCodecs();
QList<int> supportedSampleRates();
QList<int> supportedChannelCounts();
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
static QByteArray defaultInputDevice();
static QByteArray defaultOutputDevice();
static QList<QByteArray> availableDevices(QAudio::Mode);
private:
QAudio::Mode mode;
QString device;
quint32 devId;
QAudioFormat nearest;
QList<int> freqz;
QList<int> channelz;
QList<int> sizez;
QList<QAudioFormat::Endian> byteOrderz;
QStringList codecz;
QList<QAudioFormat::SampleType> typez;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,407 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <qaudioformat.h>
QT_BEGIN_NAMESPACE
class QAudioFormatPrivate : public QSharedData
{
public:
QAudioFormatPrivate()
{
frequency = -1;
channels = -1;
sampleSize = -1;
byteOrder = QAudioFormat::Endian(QSysInfo::ByteOrder);
sampleType = QAudioFormat::Unknown;
}
QAudioFormatPrivate(const QAudioFormatPrivate &other):
QSharedData(other),
codec(other.codec),
byteOrder(other.byteOrder),
sampleType(other.sampleType),
frequency(other.frequency),
channels(other.channels),
sampleSize(other.sampleSize)
{
}
QAudioFormatPrivate& operator=(const QAudioFormatPrivate &other)
{
codec = other.codec;
byteOrder = other.byteOrder;
sampleType = other.sampleType;
frequency = other.frequency;
channels = other.channels;
sampleSize = other.sampleSize;
return *this;
}
QString codec;
QAudioFormat::Endian byteOrder;
QAudioFormat::SampleType sampleType;
int frequency;
int channels;
int sampleSize;
};
/*!
\class QAudioFormat
\brief The QAudioFormat class stores audio stream parameter information.
\inmodule QtMultimediaKit
\ingroup multimedia
\since 1.0
An audio format specifies how data in an audio stream is arranged,
i.e, how the stream is to be interpreted. The encoding itself is
specified by the codec() used for the stream.
In addition to the encoding, QAudioFormat contains other
parameters that further specify how the audio sample data is arranged.
These are the frequency, the number of channels, the sample size,
the sample type, and the byte order. The following table describes
these in more detail.
\table
\header
\o Parameter
\o Description
\row
\o Sample Rate
\o Samples per second of audio data in Hertz.
\row
\o Number of channels
\o The number of audio channels (typically one for mono
or two for stereo)
\row
\o Sample size
\o How much data is stored in each sample (typically 8
or 16 bits)
\row
\o Sample type
\o Numerical representation of sample (typically signed integer,
unsigned integer or float)
\row
\o Byte order
\o Byte ordering of sample (typically little endian, big endian)
\endtable
This class is typically used in conjunction with QAudioInput or
QAudioOutput to allow you to specify the parameters of the audio
stream being read or written.
You can obtain audio formats compatible with the audio device used
through functions in QAudioDeviceInfo. This class also lets you
query available parameter values for a device, so that you can set
the parameters yourself. See the \l QAudioDeviceInfo class
description for details. You need to know the format of the audio
streams you wish to play or record.
*/
/*!
Construct a new audio format.
Values are initialized as follows:
\list
\o sampleRate() = -1
\o channelCount() = -1
\o sampleSize() = -1
\o byteOrder() = QAudioFormat::Endian(QSysInfo::ByteOrder)
\o sampleType() = QAudioFormat::Unknown
\c codec() = ""
\endlist
*/
QAudioFormat::QAudioFormat():
d(new QAudioFormatPrivate)
{
}
/*!
Construct a new audio format using \a other.
\since 1.0
*/
QAudioFormat::QAudioFormat(const QAudioFormat &other):
d(other.d)
{
}
/*!
Destroy this audio format.
*/
QAudioFormat::~QAudioFormat()
{
}
/*!
Assigns \a other to this QAudioFormat implementation.
\since 1.0
*/
QAudioFormat& QAudioFormat::operator=(const QAudioFormat &other)
{
d = other.d;
return *this;
}
/*!
Returns true if this QAudioFormat is equal to the \a other
QAudioFormat; otherwise returns false.
All elements of QAudioFormat are used for the comparison.
\since 1.0
*/
bool QAudioFormat::operator==(const QAudioFormat &other) const
{
return d->frequency == other.d->frequency &&
d->channels == other.d->channels &&
d->sampleSize == other.d->sampleSize &&
d->byteOrder == other.d->byteOrder &&
d->codec == other.d->codec &&
d->sampleType == other.d->sampleType;
}
/*!
Returns true if this QAudioFormat is not equal to the \a other
QAudioFormat; otherwise returns false.
All elements of QAudioFormat are used for the comparison.
\since 1.0
*/
bool QAudioFormat::operator!=(const QAudioFormat& other) const
{
return !(*this == other);
}
/*!
Returns true if all of the parameters are valid.
\since 1.0
*/
bool QAudioFormat::isValid() const
{
return d->frequency != -1 && d->channels != -1 && d->sampleSize != -1 &&
d->sampleType != QAudioFormat::Unknown && !d->codec.isEmpty();
}
/*!
Sets the sample rate to \a samplerate Hertz.
\since 1.0
*/
void QAudioFormat::setSampleRate(int samplerate)
{
d->frequency = samplerate;
}
/*!
\obsolete
Use setSampleRate() instead.
*/
void QAudioFormat::setFrequency(int frequency)
{
d->frequency = frequency;
}
/*!
Returns the current sample rate in Hertz.
\since 1.0
*/
int QAudioFormat::sampleRate() const
{
return d->frequency;
}
/*!
\obsolete
Use sampleRate() instead.
*/
int QAudioFormat::frequency() const
{
return d->frequency;
}
/*!
Sets the channel count to \a channels.
\since 1.0
*/
void QAudioFormat::setChannelCount(int channels)
{
d->channels = channels;
}
/*!
\obsolete
Use setChannelCount() instead.
*/
void QAudioFormat::setChannels(int channels)
{
d->channels = channels;
}
/*!
Returns the current channel count value.
\since 1.0
*/
int QAudioFormat::channelCount() const
{
return d->channels;
}
/*!
\obsolete
Use channelCount() instead.
*/
int QAudioFormat::channels() const
{
return d->channels;
}
/*!
Sets the sample size to the \a sampleSize specified, in bits.
This is typically 8 or 16, but some systems may support higher sample sizes.
\since 1.0
*/
void QAudioFormat::setSampleSize(int sampleSize)
{
d->sampleSize = sampleSize;
}
/*!
Returns the current sample size value, in bits.
\since 1.0
*/
int QAudioFormat::sampleSize() const
{
return d->sampleSize;
}
/*!
Sets the codec to \a codec.
The parameter to this function should be one of the types
reported by the QAudioDeviceInfo::supportedCodecs() function
for the audio device you are working with.
\since 1.0
\sa QAudioDeviceInfo::supportedCodecs()
*/
void QAudioFormat::setCodec(const QString &codec)
{
d->codec = codec;
}
/*!
Returns the current codec identifier.
\since 1.0
\sa QAudioDeviceInfo::supportedCodecs()
*/
QString QAudioFormat::codec() const
{
return d->codec;
}
/*!
Sets the byteOrder to \a byteOrder.
\since 1.0
*/
void QAudioFormat::setByteOrder(QAudioFormat::Endian byteOrder)
{
d->byteOrder = byteOrder;
}
/*!
Returns the current byteOrder value.
\since 1.0
*/
QAudioFormat::Endian QAudioFormat::byteOrder() const
{
return d->byteOrder;
}
/*!
Sets the sampleType to \a sampleType.
\since 1.0
*/
void QAudioFormat::setSampleType(QAudioFormat::SampleType sampleType)
{
d->sampleType = sampleType;
}
/*!
Returns the current SampleType value.
\since 1.0
*/
QAudioFormat::SampleType QAudioFormat::sampleType() const
{
return d->sampleType;
}
/*!
\enum QAudioFormat::SampleType
\value Unknown Not Set
\value SignedInt Samples are signed integers
\value UnSignedInt Samples are unsigned intergers
\value Float Samples are floats
*/
/*!
\enum QAudioFormat::Endian
\value BigEndian Samples are big endian byte order
\value LittleEndian Samples are little endian byte order
*/
QT_END_NAMESPACE

View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIOFORMAT_H
#define QAUDIOFORMAT_H
#include <QtCore/qobject.h>
#include <QtCore/qshareddata.h>
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QAudioFormatPrivate;
class Q_MULTIMEDIA_EXPORT QAudioFormat
{
public:
enum SampleType { Unknown, SignedInt, UnSignedInt, Float };
enum Endian { BigEndian = QSysInfo::BigEndian, LittleEndian = QSysInfo::LittleEndian };
QAudioFormat();
QAudioFormat(const QAudioFormat &other);
~QAudioFormat();
QAudioFormat& operator=(const QAudioFormat &other);
bool operator==(const QAudioFormat &other) const;
bool operator!=(const QAudioFormat &other) const;
bool isValid() const;
void setFrequency(int frequency);
int frequency() const;
void setSampleRate(int sampleRate);
int sampleRate() const;
void setChannels(int channels);
int channels() const;
void setChannelCount(int channelCount);
int channelCount() const;
void setSampleSize(int sampleSize);
int sampleSize() const;
void setCodec(const QString &codec);
QString codec() const;
void setByteOrder(QAudioFormat::Endian byteOrder);
QAudioFormat::Endian byteOrder() const;
void setSampleType(QAudioFormat::SampleType sampleType);
QAudioFormat::SampleType sampleType() const;
private:
QSharedDataPointer<QAudioFormatPrivate> d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOFORMAT_H

View File

@@ -0,0 +1,426 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
#include "qaudioinput.h"
#include "qaudiodevicefactory_p.h"
QT_BEGIN_NAMESPACE
/*!
\class QAudioInput
\brief The QAudioInput class provides an interface for receiving audio data from an audio input device.
\inmodule QtMultimediaKit
\ingroup multimedia
\since 1.0
XXX Needs more blurb about use cases etc
Link to terminology etc
Push/Pull mode
State diagram
You can construct an audio input with the system's
\l{QAudioDeviceInfo::defaultInputDevice()}{default audio input
device}. It is also possible to create QAudioInput with a
specific QAudioDeviceInfo. When you create the audio input, you
should also send in the QAudioFormat to be used for the recording
(see the QAudioFormat class description for details).
To record to a file:
QAudioInput lets you record audio with an audio input device. The
default constructor of this class will use the systems default
audio device, but you can also specify a QAudioDeviceInfo for a
specific device. You also need to pass in the QAudioFormat in
which you wish to record.
Starting up the QAudioInput is simply a matter of calling start()
with a QIODevice opened for writing. For instance, to record to a
file, you can:
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input class members
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input setup
This will start recording if the format specified is supported by
the input device (you can check this with
QAudioDeviceInfo::isFormatSupported(). In case there are any
snags, use the error() function to check what went wrong. We stop
recording in the \c stopRecording() slot.
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input stop recording
At any point in time, QAudioInput will be in one of four states:
active, suspended, stopped, or idle. These states are specified by
the QAudio::State enum. You can request a state change directly through
suspend(), resume(), stop(), reset(), and start(). The current
state is reported by state(). QAudioOutput will also signal you
when the state changes (stateChanged()).
QAudioInput provides several ways of measuring the time that has
passed since the start() of the recording. The \c processedUSecs()
function returns the length of the stream in microseconds written,
i.e., it leaves out the times the audio input was suspended or idle.
The elapsedUSecs() function returns the time elapsed since start() was called regardless of
which states the QAudioInput has been in.
If an error should occur, you can fetch its reason with error().
The possible error reasons are described by the QAudio::Error
enum. The QAudioInput will enter the \l{QAudio::}{StoppedState} when
an error is encountered. Connect to the stateChanged() signal to
handle the error:
\snippet doc/src/snippets/multimedia-snippets/audio.cpp Audio input state changed
\sa QAudioOutput, QAudioDeviceInfo
\section1 Symbian Platform Security Requirements
On Symbian, processes which use this class must have the
\c UserEnvironment platform security capability. If the client
process lacks this capability, calls to either overload of start()
will fail.
This failure is indicated by the QAudioInput object setting
its error() value to \l{QAudio::OpenError} and then emitting a
\l{stateChanged()}{stateChanged}(\l{QAudio::StoppedState}) signal.
Platform security capabilities are added via the
\l{qmake-variable-reference.html#target-capability}{TARGET.CAPABILITY}
qmake variable.
*/
/*!
Construct a new audio input and attach it to \a parent.
The default audio input device is used with the output
\a format parameters.
\since 1.0
*/
QAudioInput::QAudioInput(const QAudioFormat &format, QObject *parent):
QObject(parent)
{
d = QAudioDeviceFactory::createDefaultInputDevice(format);
connect(d, SIGNAL(notify()), SIGNAL(notify()));
connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
}
/*!
Construct a new audio input and attach it to \a parent.
The device referenced by \a audioDevice is used with the input
\a format parameters.
\since 1.0
*/
QAudioInput::QAudioInput(const QAudioDeviceInfo &audioDevice, const QAudioFormat &format, QObject *parent):
QObject(parent)
{
d = QAudioDeviceFactory::createInputDevice(audioDevice, format);
connect(d, SIGNAL(notify()), SIGNAL(notify()));
connect(d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
}
/*!
Destroy this audio input.
*/
QAudioInput::~QAudioInput()
{
delete d;
}
/*!
Uses the \a device as the QIODevice to transfer data.
Passing a QIODevice allows the data to be transferred without any extra code.
All that is required is to open the QIODevice.
If able to successfully get audio data from the systems audio device the
state() is set to either QAudio::ActiveState or QAudio::IdleState,
error() is set to QAudio::NoError and the stateChanged() signal is emitted.
If a problem occurs during this process the error() is set to QAudio::OpenError,
state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
\l{QAudioInput#Symbian Platform Security Requirements}
\since 1.0
\sa QIODevice
*/
void QAudioInput::start(QIODevice* device)
{
d->start(device);
}
/*!
Returns a pointer to the QIODevice being used to handle the data
transfer. This QIODevice can be used to read() audio data
directly.
If able to access the systems audio device the state() is set to
QAudio::IdleState, error() is set to QAudio::NoError
and the stateChanged() signal is emitted.
If a problem occurs during this process the error() is set to QAudio::OpenError,
state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
\l{QAudioInput#Symbian Platform Security Requirements}
\since 1.0
\sa QIODevice
*/
QIODevice* QAudioInput::start()
{
return d->start();
}
/*!
Returns the QAudioFormat being used.
\since 1.0
*/
QAudioFormat QAudioInput::format() const
{
return d->format();
}
/*!
Stops the audio input, detaching from the system resource.
Sets error() to QAudio::NoError, state() to QAudio::StoppedState and
emit stateChanged() signal.
\since 1.0
*/
void QAudioInput::stop()
{
d->stop();
}
/*!
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
void QAudioInput::reset()
{
d->reset();
}
/*!
Stops processing audio data, preserving buffered audio data.
Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
emit stateChanged() signal.
\since 1.0
*/
void QAudioInput::suspend()
{
d->suspend();
}
/*!
Resumes processing audio data after a suspend().
Sets error() to QAudio::NoError.
Sets state() to QAudio::ActiveState if you previously called start(QIODevice*).
Sets state() to QAudio::IdleState if you previously called start().
emits stateChanged() signal.
\since 1.0
*/
void QAudioInput::resume()
{
d->resume();
}
/*!
Sets the audio buffer size to \a value milliseconds.
Note: This function can be called anytime before start(), calls to this
are ignored after start(). It should not be assumed that the buffer size
set is the actual buffer size used, calling bufferSize() anytime after start()
will return the actual buffer size being used.
\since 1.0
*/
void QAudioInput::setBufferSize(int value)
{
d->setBufferSize(value);
}
/*!
Returns the audio buffer size in milliseconds.
If called before start(), returns platform default value.
If called before start() but setBufferSize() was called prior, returns value set by setBufferSize().
If called after start(), returns the actual buffer size being used. This may not be what was set previously
by setBufferSize().
\since 1.0
*/
int QAudioInput::bufferSize() const
{
return d->bufferSize();
}
/*!
Returns the amount of audio data available to read in bytes.
NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState
state, otherwise returns zero.
\since 1.0
*/
int QAudioInput::bytesReady() const
{
/*
-If not ActiveState|IdleState, return 0
-return amount of audio data available to read
*/
return d->bytesReady();
}
/*!
Returns the period size in bytes.
Note: This is the recommended read size in bytes.
\since 1.0
*/
int QAudioInput::periodSize() const
{
return d->periodSize();
}
/*!
Sets the interval for notify() signal to be emitted.
This is based on the \a ms of audio data processed
not on actual real-time.
The minimum resolution of the timer is platform specific and values
should be checked with notifyInterval() to confirm actual value
being used.
\since 1.0
*/
void QAudioInput::setNotifyInterval(int ms)
{
d->setNotifyInterval(ms);
}
/*!
Returns the notify interval in milliseconds.
\since 1.0
*/
int QAudioInput::notifyInterval() const
{
return d->notifyInterval();
}
/*!
Returns the amount of audio data processed since start()
was called in microseconds.
\since 1.0
*/
qint64 QAudioInput::processedUSecs() const
{
return d->processedUSecs();
}
/*!
Returns the microseconds since start() was called, including time in Idle and
Suspend states.
\since 1.0
*/
qint64 QAudioInput::elapsedUSecs() const
{
return d->elapsedUSecs();
}
/*!
Returns the error state.
\since 1.0
*/
QAudio::Error QAudioInput::error() const
{
return d->error();
}
/*!
Returns the state of audio processing.
\since 1.0
*/
QAudio::State QAudioInput::state() const
{
return d->state();
}
/*!
\fn QAudioInput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
\since 1.0
*/
/*!
\fn QAudioInput::notify()
This signal is emitted when x ms of audio data has been processed
the interval set by setNotifyInterval(x).
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudioinput.cpp"

View File

@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIOINPUT_H
#define QAUDIOINPUT_H
#include <QtCore/qiodevice.h>
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiodeviceinfo.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QAbstractAudioInput;
class Q_MULTIMEDIA_EXPORT QAudioInput : public QObject
{
Q_OBJECT
public:
explicit QAudioInput(const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
explicit QAudioInput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
~QAudioInput();
QAudioFormat format() const;
void start(QIODevice *device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
void setBufferSize(int bytes);
int bufferSize() const;
int bytesReady() const;
int periodSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
Q_SIGNALS:
void stateChanged(QAudio::State);
void notify();
private:
Q_DISABLE_COPY(QAudioInput)
QAbstractAudioInput* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOINPUT_H

View File

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

View File

@@ -0,0 +1,183 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUTALSA_H
#define QAUDIOINPUTALSA_H
#include <alsa/asoundlib.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_NAMESPACE
class InputPrivate;
class RingBuffer
{
public:
RingBuffer();
void resize(int size);
int bytesOfDataInBuffer() const;
int freeBytes() const;
const char *availableData() const;
int availableDataBlockSize() const;
void readBytes(int bytes);
void write(char *data, int len);
private:
int m_head;
int m_tail;
QByteArray m_data;
};
class QAudioInputPrivate : public QAbstractAudioInput
{
Q_OBJECT
public:
QAudioInputPrivate(const QByteArray &device);
~QAudioInputPrivate();
qint64 read(char* data, qint64 len);
void start(QIODevice* device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
bool resuming;
snd_pcm_t* handle;
qint64 totalTimeValue;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private slots:
void userFeed();
bool deviceReady();
private:
int checkBytesReady();
int xrun_recovery(int err);
int setFormat();
bool open();
void close();
void drain();
QTimer* timer;
QTime timeStamp;
QTime clockStamp;
qint64 elapsedTimeOffset;
int intervalTime;
RingBuffer ringBuffer;
int bytesAvailable;
QByteArray m_device;
bool pullMode;
int buffer_size;
int period_size;
unsigned int buffer_time;
unsigned int period_time;
snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames;
snd_async_handler_t* ahandler;
snd_pcm_access_t access;
snd_pcm_format_t pcmformat;
snd_timestamp_t* timestamp;
snd_pcm_hw_params_t *hwparams;
};
class InputPrivate : public QIODevice
{
Q_OBJECT
public:
InputPrivate(QAudioInputPrivate* audio);
~InputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
void trigger();
private:
QAudioInputPrivate *audioDevice;
};
QT_END_NAMESPACE
#endif

View File

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

View File

@@ -0,0 +1,171 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUT_MAC_P_H
#define QAUDIOINPUT_MAC_P_H
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QtCore/qobject.h>
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
#include <QtCore/qatomic.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QTimer;
class QIODevice;
class QAbstractAudioDeviceInfo;
namespace QtMultimediaKitInternal
{
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;
QtMultimediaKitInternal::QAudioInputBuffer* audioBuffer;
QMutex mutex;
QWaitCondition threadFinished;
QAtomicInt audioThreadState;
QTimer* intervalTimer;
AudioStreamBasicDescription streamFormat;
AudioStreamBasicDescription deviceFormat;
QAbstractAudioDeviceInfo *audioDeviceInfo;
QAudioInputPrivate(const QByteArray& device);
~QAudioInputPrivate();
bool open();
void close();
QAudioFormat format() const;
void setFormat(const QAudioFormat& fmt);
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
void idle();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void audioThreadStart();
void audioThreadStop();
void audioDeviceStop();
void audioDeviceFull();
void audioDeviceError();
void startTimers();
void stopTimers();
private slots:
void deviceStopped();
private:
enum { Running, Stopped };
// Input callback
static OSStatus inputCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOINPUT_MAC_P_H

View File

@@ -0,0 +1,594 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudioinput_symbian_p.h"
QT_BEGIN_NAMESPACE
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const int PushInterval = 50; // ms
//-----------------------------------------------------------------------------
// Private class
//-----------------------------------------------------------------------------
SymbianAudioInputPrivate::SymbianAudioInputPrivate(
QAudioInputPrivate *audioDevice)
: m_audioDevice(audioDevice)
{
}
SymbianAudioInputPrivate::~SymbianAudioInputPrivate()
{
}
qint64 SymbianAudioInputPrivate::readData(char *data, qint64 len)
{
qint64 totalRead = 0;
if (m_audioDevice->state() == QAudio::ActiveState ||
m_audioDevice->state() == QAudio::IdleState) {
while (totalRead < len) {
const qint64 read = m_audioDevice->read(data + totalRead,
len - totalRead);
if (read > 0)
totalRead += read;
else
break;
}
}
return totalRead;
}
qint64 SymbianAudioInputPrivate::writeData(const char *data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)
return 0;
}
void SymbianAudioInputPrivate::dataReady()
{
emit readyRead();
}
//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------
QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device)
: m_device(device)
, m_clientBufferSize(SymbianAudio::DefaultBufferSize)
, m_notifyInterval(SymbianAudio::DefaultNotifyInterval)
, m_notifyTimer(new QTimer(this))
, m_lastNotifyPosition(0)
, m_error(QAudio::NoError)
, m_internalState(SymbianAudio::ClosedState)
, m_externalState(QAudio::StoppedState)
, m_pullMode(false)
, m_sink(0)
, m_pullTimer(new QTimer(this))
, m_devSound(0)
, m_devSoundBuffer(0)
, m_devSoundBufferSize(0)
, m_totalBytesReady(0)
, m_devSoundBufferPos(0)
, m_totalSamplesRecorded(0)
{
qRegisterMetaType<CMMFBuffer *>("CMMFBuffer *");
connect(m_notifyTimer.data(), SIGNAL(timeout()),
this, SIGNAL(notifyTimerExpired()));
m_pullTimer->setInterval(PushInterval);
connect(m_pullTimer.data(), SIGNAL(timeout()), this, SLOT(pullData()));
}
void QAudioInputPrivate::setFormat(const QAudioFormat& fmt)
{
m_format = fmt;
}
QAudioInputPrivate::~QAudioInputPrivate()
{
close();
}
void QAudioInputPrivate::start(QIODevice *device)
{
stop();
open();
if (SymbianAudio::ClosedState != m_internalState) {
m_pullMode = true;
m_sink = device;
m_elapsed.restart();
}
}
QIODevice* QAudioInputPrivate::start()
{
stop();
open();
if (SymbianAudio::ClosedState != m_internalState) {
m_sink = new SymbianAudioInputPrivate(this);
m_sink->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
m_elapsed.restart();
}
return m_sink;
}
void QAudioInputPrivate::stop()
{
close();
}
void QAudioInputPrivate::reset()
{
m_totalSamplesRecorded += getSamplesRecorded();
m_devSound->stop();
startRecording();
}
void QAudioInputPrivate::suspend()
{
if (SymbianAudio::ActiveState == m_internalState
|| SymbianAudio::IdleState == m_internalState) {
m_pullTimer->stop();
const qint64 samplesRecorded = getSamplesRecorded();
m_totalSamplesRecorded += samplesRecorded;
const bool paused = m_devSound->pause();
if (paused) {
if (m_devSoundBuffer)
m_devSoundBufferQ.append(m_devSoundBuffer);
m_devSoundBuffer = 0;
setState(SymbianAudio::SuspendedPausedState);
} else {
m_devSoundBuffer = 0;
m_devSoundBufferQ.clear();
m_devSoundBufferPos = 0;
setState(SymbianAudio::SuspendedStoppedState);
}
}
}
void QAudioInputPrivate::resume()
{
if (QAudio::SuspendedState == m_externalState) {
if (SymbianAudio::SuspendedPausedState == m_internalState)
m_devSound->resume();
else
m_devSound->start();
startDataTransfer();
}
}
int QAudioInputPrivate::bytesReady() const
{
Q_ASSERT(m_devSoundBufferPos <= m_totalBytesReady);
return m_totalBytesReady - m_devSoundBufferPos;
}
int QAudioInputPrivate::periodSize() const
{
return bufferSize();
}
void QAudioInputPrivate::setBufferSize(int value)
{
// Note that DevSound does not allow its client to specify the buffer size.
// This functionality is available via custom interfaces, but since these
// cannot be guaranteed to work across all DevSound implementations, we
// do not use them here.
// In order to comply with the expected bevahiour of QAudioInput, we store
// the value and return it from bufferSize(), but the underlying DevSound
// buffer size remains unchanged.
if (value > 0)
m_clientBufferSize = value;
}
int QAudioInputPrivate::bufferSize() const
{
return m_devSoundBufferSize ? m_devSoundBufferSize : m_clientBufferSize;
}
void QAudioInputPrivate::setNotifyInterval(int ms)
{
if (ms >= 0) {
//const int oldNotifyInterval = m_notifyInterval;
m_notifyInterval = ms;
if (m_notifyInterval && (SymbianAudio::ActiveState == m_internalState ||
SymbianAudio::IdleState == m_internalState))
m_notifyTimer->start(m_notifyInterval);
else
m_notifyTimer->stop();
}
}
int QAudioInputPrivate::notifyInterval() const
{
return m_notifyInterval;
}
qint64 QAudioInputPrivate::processedUSecs() const
{
int samplesPlayed = 0;
if (m_devSound && QAudio::SuspendedState != m_externalState)
samplesPlayed = getSamplesRecorded();
// Protect against division by zero
Q_ASSERT_X(m_format.frequency() > 0, Q_FUNC_INFO, "Invalid frequency");
const qint64 result = qint64(1000000) *
(samplesPlayed + m_totalSamplesRecorded)
/ m_format.frequency();
return result;
}
qint64 QAudioInputPrivate::elapsedUSecs() const
{
const qint64 result = (QAudio::StoppedState == state()) ?
0 : m_elapsed.elapsed() * 1000;
return result;
}
QAudio::Error QAudioInputPrivate::error() const
{
return m_error;
}
QAudio::State QAudioInputPrivate::state() const
{
return m_externalState;
}
QAudioFormat QAudioInputPrivate::format() const
{
return m_format;
}
//-----------------------------------------------------------------------------
// Private functions
//-----------------------------------------------------------------------------
void QAudioInputPrivate::open()
{
Q_ASSERT_X(SymbianAudio::ClosedState == m_internalState,
Q_FUNC_INFO, "DevSound already opened");
Q_ASSERT(!m_devSound);
m_devSound = new SymbianAudio::DevSoundWrapper(QAudio::AudioInput, this);
connect(m_devSound, SIGNAL(initializeComplete(int)),
this, SLOT(devsoundInitializeComplete(int)));
connect(m_devSound, SIGNAL(bufferToBeProcessed(CMMFBuffer *)),
this, SLOT(devsoundBufferToBeEmptied(CMMFBuffer *)));
connect(m_devSound, SIGNAL(processingError(int)),
this, SLOT(devsoundRecordError(int)));
setState(SymbianAudio::InitializingState);
m_devSound->initialize(m_format.codec());
}
void QAudioInputPrivate::startRecording()
{
const int samplesRecorded = m_devSound->samplesProcessed();
Q_ASSERT(samplesRecorded == 0);
bool ok = m_devSound->setFormat(m_format);
if (ok)
ok = m_devSound->start();
if (ok) {
startDataTransfer();
} else {
setError(QAudio::OpenError);
close();
}
}
void QAudioInputPrivate::startDataTransfer()
{
if (m_notifyInterval)
m_notifyTimer->start(m_notifyInterval);
if (m_pullMode)
m_pullTimer->start();
if (bytesReady()) {
setState(SymbianAudio::ActiveState);
if (!m_pullMode)
pushData();
} else {
if (QAudio::SuspendedState == m_externalState)
setState(SymbianAudio::ActiveState);
else
setState(SymbianAudio::IdleState);
}
}
CMMFDataBuffer* QAudioInputPrivate::currentBuffer() const
{
CMMFDataBuffer *result = m_devSoundBuffer;
if (!result && !m_devSoundBufferQ.empty())
result = m_devSoundBufferQ.front();
return result;
}
void QAudioInputPrivate::pushData()
{
Q_ASSERT_X(bytesReady(), Q_FUNC_INFO, "No data available");
Q_ASSERT_X(!m_pullMode, Q_FUNC_INFO, "pushData called when in pull mode");
qobject_cast<SymbianAudioInputPrivate *>(m_sink)->dataReady();
}
qint64 QAudioInputPrivate::read(char *data, qint64 len)
{
// SymbianAudioInputPrivate is ready to read data
Q_ASSERT_X(!m_pullMode, Q_FUNC_INFO,
"read called when in pull mode");
qint64 bytesRead = 0;
CMMFDataBuffer *buffer = 0;
buffer = currentBuffer();
while (buffer && (bytesRead < len)) {
if (SymbianAudio::IdleState == m_internalState)
setState(SymbianAudio::ActiveState);
TDesC8 &inputBuffer = buffer->Data();
Q_ASSERT(inputBuffer.Length() >= m_devSoundBufferPos);
const qint64 inputBytes = inputBuffer.Length() - m_devSoundBufferPos;
const qint64 outputBytes = len - bytesRead;
const qint64 copyBytes = outputBytes < inputBytes ?
outputBytes : inputBytes;
memcpy(data, inputBuffer.Ptr() + m_devSoundBufferPos, copyBytes);
m_devSoundBufferPos += copyBytes;
data += copyBytes;
bytesRead += copyBytes;
if (inputBytes == copyBytes)
bufferEmptied();
buffer = currentBuffer();
}
return bytesRead;
}
void QAudioInputPrivate::notifyTimerExpired()
{
const qint64 pos = processedUSecs();
if (pos > m_lastNotifyPosition) {
int count = (pos - m_lastNotifyPosition) / (m_notifyInterval * 1000);
while (count--) {
emit notify();
m_lastNotifyPosition += m_notifyInterval * 1000;
}
}
}
void QAudioInputPrivate::pullData()
{
Q_ASSERT_X(m_pullMode, Q_FUNC_INFO,
"pullData called when in push mode");
CMMFDataBuffer *buffer = 0;
buffer = currentBuffer();
while (buffer) {
if (SymbianAudio::IdleState == m_internalState)
setState(SymbianAudio::ActiveState);
TDesC8 &inputBuffer = buffer->Data();
Q_ASSERT(inputBuffer.Length() >= m_devSoundBufferPos);
const qint64 inputBytes = inputBuffer.Length() - m_devSoundBufferPos;
const qint64 bytesPushed = m_sink->write(
(char*)inputBuffer.Ptr() + m_devSoundBufferPos, inputBytes);
m_devSoundBufferPos += bytesPushed;
if (inputBytes == bytesPushed)
bufferEmptied();
if (!bytesPushed)
break;
buffer = currentBuffer();
}
}
void QAudioInputPrivate::devsoundInitializeComplete(int err)
{
Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState,
Q_FUNC_INFO, "Invalid state");
if (!err && m_devSound->isFormatSupported(m_format))
startRecording();
else
setError(QAudio::OpenError);
}
void QAudioInputPrivate::devsoundBufferToBeEmptied(CMMFBuffer *baseBuffer)
{
// Following receipt of this signal, DevSound should not provide another
// buffer until we have returned the current one.
Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held");
CMMFDataBuffer *const buffer = static_cast<CMMFDataBuffer*>(baseBuffer);
if (!m_devSoundBufferSize)
m_devSoundBufferSize = buffer->Data().MaxLength();
m_totalBytesReady += buffer->Data().Length();
if (SymbianAudio::SuspendedPausedState == m_internalState) {
m_devSoundBufferQ.append(buffer);
} else {
// Will be returned to DevSoundWrapper by bufferProcessed().
m_devSoundBuffer = buffer;
m_devSoundBufferPos = 0;
if (bytesReady() && !m_pullMode)
pushData();
}
}
void QAudioInputPrivate::devsoundRecordError(int err)
{
Q_UNUSED(err)
setError(QAudio::IOError);
}
void QAudioInputPrivate::bufferEmptied()
{
m_devSoundBufferPos = 0;
if (m_devSoundBuffer) {
m_totalBytesReady -= m_devSoundBuffer->Data().Length();
m_devSoundBuffer = 0;
m_devSound->bufferProcessed();
} else {
Q_ASSERT(!m_devSoundBufferQ.empty());
m_totalBytesReady -= m_devSoundBufferQ.front()->Data().Length();
m_devSoundBufferQ.erase(m_devSoundBufferQ.begin());
// If the queue has been emptied, resume transfer from the hardware
if (m_devSoundBufferQ.empty())
if (!m_devSound->start())
setError(QAudio::IOError);
}
Q_ASSERT(m_totalBytesReady >= 0);
}
void QAudioInputPrivate::close()
{
m_lastNotifyPosition = 0;
m_pullTimer->stop();
m_error = QAudio::NoError;
if (m_devSound)
m_devSound->stop();
delete m_devSound;
m_devSound = 0;
m_devSoundBuffer = 0;
m_devSoundBufferSize = 0;
m_totalBytesReady = 0;
if (!m_pullMode) // m_sink is owned
delete m_sink;
m_pullMode = false;
m_sink = 0;
m_devSoundBufferQ.clear();
m_devSoundBufferPos = 0;
m_totalSamplesRecorded = 0;
setState(SymbianAudio::ClosedState);
}
qint64 QAudioInputPrivate::getSamplesRecorded() const
{
qint64 result = 0;
if (m_devSound)
result = qint64(m_devSound->samplesProcessed());
return result;
}
void QAudioInputPrivate::setError(QAudio::Error error)
{
m_error = error;
// Although no state transition actually occurs here, a stateChanged event
// must be emitted to inform the client that the call to start() was
// unsuccessful.
if (QAudio::OpenError == error) {
emit stateChanged(QAudio::StoppedState);
} else {
if (QAudio::UnderrunError == error)
setState(SymbianAudio::IdleState);
else
// Close the DevSound instance. This causes a transition to
// StoppedState. This must be done asynchronously in case the
// current function was called from a DevSound event handler, in which
// case deleting the DevSound instance may cause an exception.
QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
}
}
void QAudioInputPrivate::setState(SymbianAudio::State newInternalState)
{
const QAudio::State oldExternalState = m_externalState;
m_internalState = newInternalState;
m_externalState = SymbianAudio::Utils::stateNativeToQt(m_internalState);
if (m_externalState != QAudio::ActiveState &&
m_externalState != QAudio::IdleState)
m_notifyTimer->stop();
if (m_externalState != oldExternalState)
emit stateChanged(m_externalState);
}
QT_END_NAMESPACE
#include "moc_qaudioinput_symbian_p.cpp"

View File

@@ -0,0 +1,178 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUT_SYMBIAN_P_H
#define QAUDIOINPUT_SYMBIAN_P_H
#include <qaudiosystem.h>
#include <QTime>
#include <QTimer>
#include "qaudio_symbian_p.h"
QT_BEGIN_NAMESPACE
class QAudioInputPrivate;
class SymbianAudioInputPrivate : public QIODevice
{
friend class QAudioInputPrivate;
Q_OBJECT
public:
SymbianAudioInputPrivate(QAudioInputPrivate *audio);
~SymbianAudioInputPrivate();
qint64 readData(char *data, qint64 len);
qint64 writeData(const char *data, qint64 len);
void dataReady();
private:
QAudioInputPrivate *const m_audioDevice;
};
class QAudioInputPrivate
: public QAbstractAudioInput
{
friend class SymbianAudioInputPrivate;
Q_OBJECT
public:
QAudioInputPrivate(const QByteArray &device);
~QAudioInputPrivate();
// QAbstractAudioInput
void start(QIODevice *device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
QAudioFormat format() const;
void setFormat(const QAudioFormat& fmt);
private slots:
void notifyTimerExpired();
void pullData();
void devsoundInitializeComplete(int err);
void devsoundBufferToBeEmptied(CMMFBuffer *);
void devsoundRecordError(int err);
private:
void open();
void startRecording();
void startDataTransfer();
CMMFDataBuffer* currentBuffer() const;
void pushData();
qint64 read(char *data, qint64 len);
void bufferEmptied();
Q_INVOKABLE void close();
qint64 getSamplesRecorded() const;
void setError(QAudio::Error error);
void setState(SymbianAudio::State state);
private:
const QByteArray m_device;
QAudioFormat m_format;
int m_clientBufferSize;
int m_notifyInterval;
QScopedPointer<QTimer> m_notifyTimer;
qint64 m_lastNotifyPosition;
QTime m_elapsed;
QAudio::Error m_error;
SymbianAudio::State m_internalState;
QAudio::State m_externalState;
bool m_pullMode;
QIODevice *m_sink;
QScopedPointer<QTimer> m_pullTimer;
SymbianAudio::DevSoundWrapper* m_devSound;
// Latest buffer provided by DevSound, to be empied of data.
CMMFDataBuffer *m_devSoundBuffer;
int m_devSoundBufferSize;
// Total amount of data in buffers provided by DevSound
int m_totalBytesReady;
// Queue of buffers returned after call to CMMFDevSound::Pause().
QList<CMMFDataBuffer *> m_devSoundBufferQ;
// Current read position within m_devSoundBuffer
qint64 m_devSoundBufferPos;
// Samples recorded up to the last call to suspend(). It is necessary
// to cache this because suspend() is implemented using
// CMMFDevSound::Stop(), which resets DevSound's SamplesRecorded() counter.
quint32 m_totalSamplesRecorded;
};
QT_END_NAMESPACE
#endif

View File

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

View File

@@ -0,0 +1,171 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOINPUTWIN_H
#define QAUDIOINPUTWIN_H
#include <windows.h>
#include <mmsystem.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmutex.h>
#include <qaudio.h>
#include <qaudiodeviceinfo.h>
#include <qaudiosystem.h>
QT_BEGIN_NAMESPACE
// For compat with 4.6
#if !defined(QT_WIN_CALLBACK)
# if defined(Q_CC_MINGW)
# define QT_WIN_CALLBACK CALLBACK __attribute__ ((force_align_arg_pointer))
# else
# define QT_WIN_CALLBACK CALLBACK
# endif
#endif
class QAudioInputPrivate : public QAbstractAudioInput
{
Q_OBJECT
public:
QAudioInputPrivate(const QByteArray &device);
~QAudioInputPrivate();
qint64 read(char* data, qint64 len);
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
int bytesReady() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private:
qint32 buffer_size;
qint32 period_size;
qint32 header;
QByteArray m_device;
int bytesAvailable;
int intervalTime;
QTime timeStamp;
qint64 elapsedTimeOffset;
QTime timeStampOpened;
qint64 totalTimeValue;
bool pullMode;
bool resuming;
WAVEFORMATEX wfx;
HWAVEIN hWaveIn;
MMRESULT result;
WAVEHDR* waveBlocks;
volatile bool finished;
volatile int waveFreeBlockCount;
int waveBlockOffset;
QMutex mutex;
static void QT_WIN_CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
WAVEHDR* allocateBlocks(int size, int count);
void freeBlocks(WAVEHDR* blockArray);
bool open();
void close();
private slots:
void feedback();
bool deviceReady();
signals:
void processMore();
};
class InputPrivate : public QIODevice
{
Q_OBJECT
public:
InputPrivate(QAudioInputPrivate* audio);
~InputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
void trigger();
private:
QAudioInputPrivate *audioDevice;
};
QT_END_NAMESPACE
#endif

View File

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

View File

@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIOOUTPUT_H
#define QAUDIOOUTPUT_H
#include <QtCore/qiodevice.h>
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiodeviceinfo.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QAbstractAudioOutput;
class Q_MULTIMEDIA_EXPORT QAudioOutput : public QObject
{
Q_OBJECT
public:
explicit QAudioOutput(const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
explicit QAudioOutput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0);
~QAudioOutput();
QAudioFormat format() const;
void start(QIODevice *device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
void setBufferSize(int bytes);
int bufferSize() const;
int bytesFree() const;
int periodSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
Q_SIGNALS:
void stateChanged(QAudio::State);
void notify();
private:
Q_DISABLE_COPY(QAudioOutput)
QAbstractAudioOutput* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOOUTPUT_H

View File

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

View File

@@ -0,0 +1,167 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUTALSA_H
#define QAUDIOOUTPUTALSA_H
#include <alsa/asoundlib.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include "qaudio.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_NAMESPACE
class OutputPrivate;
class QAudioOutputPrivate : public QAbstractAudioOutput
{
friend class OutputPrivate;
Q_OBJECT
public:
QAudioOutputPrivate(const QByteArray &device);
~QAudioOutputPrivate();
qint64 write( const char *data, qint64 len );
void start(QIODevice* device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private slots:
void userFeed();
void feedback();
void updateAvailable();
bool deviceReady();
signals:
void processMore();
private:
bool opened;
bool pullMode;
bool resuming;
int buffer_size;
int period_size;
int intervalTime;
qint64 totalTimeValue;
unsigned int buffer_time;
unsigned int period_time;
snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames;
static void async_callback(snd_async_handler_t *ahandler);
int xrun_recovery(int err);
int setFormat();
bool open();
void close();
QTimer* timer;
QByteArray m_device;
int bytesAvailable;
QTime timeStamp;
QTime clockStamp;
qint64 elapsedTimeOffset;
char* audioBuffer;
snd_pcm_t* handle;
snd_async_handler_t* ahandler;
snd_pcm_access_t access;
snd_pcm_format_t pcmformat;
snd_timestamp_t* timestamp;
snd_pcm_hw_params_t *hwparams;
};
class OutputPrivate : public QIODevice
{
friend class QAudioOutputPrivate;
Q_OBJECT
public:
OutputPrivate(QAudioOutputPrivate* audio);
~OutputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
private:
QAudioOutputPrivate *audioDevice;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,729 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QtCore/qendian.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qtimer.h>
#include <QtCore/qdebug.h>
#include <qaudiooutput.h>
#include "qaudio_mac_p.h"
#include "qaudiooutput_mac_p.h"
#include "qaudiodeviceinfo_mac_p.h"
QT_BEGIN_NAMESPACE
namespace QtMultimediaKitInternal
{
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_device = 0;
m_deviceError = false;
}
void setPrefetchDevice(QIODevice* device)
{
if (m_device != device) {
m_device = device;
if (m_device != 0)
fillBuffer();
}
}
void startFillTimer()
{
if (m_device != 0)
m_fillTimer->start(m_buffer->size() / 2 / m_maxPeriodSize * m_periodTime);
}
void stopFillTimer()
{
m_fillTimer->stop();
}
signals:
void readyRead();
private slots:
void fillBuffer()
{
const int free = m_buffer->free();
const int writeSize = free - (free % m_maxPeriodSize);
if (writeSize > 0) {
bool wecan = true;
int filled = 0;
while (!m_deviceError && wecan && filled < writeSize) {
QAudioRingBuffer::Region region = m_buffer->acquireWriteRegion(writeSize - filled);
if (region.second > 0) {
region.second = m_device->read(region.first, region.second);
if (region.second > 0)
filled += region.second;
else if (region.second == 0)
wecan = false;
else if (region.second < 0) {
m_fillTimer->stop();
region.second = 0;
m_deviceError = true;
}
}
else
wecan = false;
m_buffer->releaseWriteRegion(region);
}
if (filled > 0)
emit readyRead();
}
}
private:
bool m_deviceError;
int m_maxPeriodSize;
int m_bytesPerFrame;
int m_periodTime;
QIODevice* m_device;
QTimer* m_fillTimer;
QAudioRingBuffer* m_buffer;
};
}
class MacOutputDevice : public QIODevice
{
Q_OBJECT
public:
MacOutputDevice(QtMultimediaKitInternal::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:
QtMultimediaKitInternal::QAudioOutputBuffer* m_audioBuffer;
};
QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray& device)
{
QDataStream ds(device);
quint32 did, mode;
ds >> did >> mode;
if (QAudio::Mode(mode) == QAudio::AudioInput)
errorCode = QAudio::OpenError;
else {
audioDeviceInfo = new QAudioDeviceInfoInternal(device, QAudio::AudioOutput);
isOpen = false;
audioDeviceId = AudioDeviceID(did);
audioUnit = 0;
audioIO = 0;
startTime = 0;
totalFrames = 0;
audioBuffer = 0;
internalBufferSize = QtMultimediaKitInternal::default_buffer_size;
clockFrequency = AudioGetHostClockFrequency() / 1000;
errorCode = QAudio::NoError;
stateCode = QAudio::StoppedState;
audioThreadState = Stopped;
intervalTimer = new QTimer(this);
intervalTimer->setInterval(1000);
connect(intervalTimer, SIGNAL(timeout()), SIGNAL(notify()));
}
}
QAudioOutputPrivate::~QAudioOutputPrivate()
{
delete audioDeviceInfo;
close();
}
bool QAudioOutputPrivate::open()
{
if (errorCode != QAudio::NoError)
return false;
if (isOpen)
return true;
ComponentDescription cd;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_HALOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
// Open
Component cp = FindNextComponent(NULL, &cd);
if (cp == 0) {
qWarning() << "QAudioOutput: Failed to find HAL Output component";
return false;
}
if (OpenAComponent(cp, &audioUnit) != noErr) {
qWarning() << "QAudioOutput: Unable to Open Output Component";
return false;
}
// register callback
AURenderCallbackStruct cb;
cb.inputProc = renderCallback;
cb.inputProcRefCon = this;
if (AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
0,
&cb,
sizeof(cb)) != noErr) {
qWarning() << "QAudioOutput: Failed to set AudioUnit callback";
return false;
}
// Set Audio Device
if (AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&audioDeviceId,
sizeof(audioDeviceId)) != noErr) {
qWarning() << "QAudioOutput: Unable to use configured device";
return false;
}
// Set stream format
streamFormat = toAudioStreamBasicDescription(audioFormat);
UInt32 size = sizeof(streamFormat);
if (AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&streamFormat,
sizeof(streamFormat)) != noErr) {
qWarning() << "QAudioOutput: Unable to Set Stream information";
return false;
}
// Allocate buffer
UInt32 numberOfFrames = 0;
size = sizeof(UInt32);
if (AudioUnitGetProperty(audioUnit,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
0,
&numberOfFrames,
&size) != noErr) {
qWarning() << "QAudioInput: Failed to get audio period size";
return false;
}
periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame;
if (internalBufferSize < periodSizeBytes * 2)
internalBufferSize = periodSizeBytes * 2;
else
internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
audioBuffer = new QtMultimediaKitInternal::QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat);
connect(audioBuffer, SIGNAL(readyRead()), SLOT(inputReady())); // Pull
audioIO = new MacOutputDevice(audioBuffer, this);
// Init
if (AudioUnitInitialize(audioUnit)) {
qWarning() << "QAudioOutput: Failed to initialize AudioUnit";
return false;
}
isOpen = true;
return true;
}
void QAudioOutputPrivate::close()
{
if (audioUnit != 0) {
AudioOutputUnitStop(audioUnit);
AudioUnitUninitialize(audioUnit);
CloseComponent(audioUnit);
}
delete audioBuffer;
}
QAudioFormat QAudioOutputPrivate::format() const
{
return audioFormat;
}
void QAudioOutputPrivate::setFormat(const QAudioFormat& fmt)
{
if (stateCode == QAudio::StoppedState)
audioFormat = fmt;
}
void QAudioOutputPrivate::start(QIODevice* device)
{
QIODevice* op = device;
if (!audioDeviceInfo->isFormatSupported(audioFormat) || !open()) {
stateCode = QAudio::StoppedState;
errorCode = QAudio::OpenError;
}
reset();
audioBuffer->reset();
audioBuffer->setPrefetchDevice(op);
if (op == 0) {
op = audioIO;
stateCode = QAudio::IdleState;
}
else
stateCode = QAudio::ActiveState;
// Start
errorCode = QAudio::NoError;
totalFrames = 0;
startTime = AudioGetCurrentHostTime();
if (stateCode == QAudio::ActiveState)
audioThreadStart();
emit stateChanged(stateCode);
}
QIODevice* QAudioOutputPrivate::start()
{
if (!audioDeviceInfo->isFormatSupported(audioFormat) || !open()) {
stateCode = QAudio::StoppedState;
errorCode = QAudio::OpenError;
return audioIO;
}
reset();
audioBuffer->reset();
audioBuffer->setPrefetchDevice(0);
stateCode = QAudio::IdleState;
// Start
errorCode = QAudio::NoError;
totalFrames = 0;
startTime = AudioGetCurrentHostTime();
emit stateChanged(stateCode);
return audioIO;
}
void QAudioOutputPrivate::stop()
{
QMutexLocker lock(&mutex);
if (stateCode != QAudio::StoppedState) {
audioThreadDrain();
stateCode = QAudio::StoppedState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioOutputPrivate::reset()
{
QMutexLocker lock(&mutex);
if (stateCode != QAudio::StoppedState) {
audioThreadStop();
stateCode = QAudio::StoppedState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioOutputPrivate::suspend()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState || stateCode == QAudio::IdleState) {
audioThreadStop();
stateCode = QAudio::SuspendedState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
void QAudioOutputPrivate::resume()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::SuspendedState) {
audioThreadStart();
stateCode = QAudio::ActiveState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
int QAudioOutputPrivate::bytesFree() const
{
return audioBuffer->available();
}
int QAudioOutputPrivate::periodSize() const
{
return periodSizeBytes;
}
void QAudioOutputPrivate::setBufferSize(int bs)
{
if (stateCode == QAudio::StoppedState)
internalBufferSize = bs;
}
int QAudioOutputPrivate::bufferSize() const
{
return internalBufferSize;
}
void QAudioOutputPrivate::setNotifyInterval(int milliSeconds)
{
if (intervalTimer->interval() == milliSeconds)
return;
if (milliSeconds <= 0)
milliSeconds = 0;
intervalTimer->setInterval(milliSeconds);
}
int QAudioOutputPrivate::notifyInterval() const
{
return intervalTimer->interval();
}
qint64 QAudioOutputPrivate::processedUSecs() const
{
return totalFrames * 1000000 / audioFormat.frequency();
}
qint64 QAudioOutputPrivate::elapsedUSecs() const
{
if (stateCode == QAudio::StoppedState)
return 0;
return (AudioGetCurrentHostTime() - startTime) / (clockFrequency / 1000);
}
QAudio::Error QAudioOutputPrivate::error() const
{
return errorCode;
}
QAudio::State QAudioOutputPrivate::state() const
{
return stateCode;
}
void QAudioOutputPrivate::audioThreadStart()
{
startTimers();
audioThreadState = Running;
AudioOutputUnitStart(audioUnit);
}
void QAudioOutputPrivate::audioThreadStop()
{
stopTimers();
if (audioThreadState.testAndSetAcquire(Running, Stopped))
threadFinished.wait(&mutex);
}
void QAudioOutputPrivate::audioThreadDrain()
{
stopTimers();
if (audioThreadState.testAndSetAcquire(Running, Draining))
threadFinished.wait(&mutex);
}
void QAudioOutputPrivate::audioDeviceStop()
{
AudioOutputUnitStop(audioUnit);
audioThreadState = Stopped;
threadFinished.wakeOne();
}
void QAudioOutputPrivate::audioDeviceIdle()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState) {
audioDeviceStop();
errorCode = QAudio::UnderrunError;
stateCode = QAudio::IdleState;
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
}
void QAudioOutputPrivate::audioDeviceError()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::ActiveState) {
audioDeviceStop();
errorCode = QAudio::IOError;
stateCode = QAudio::StoppedState;
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
}
void QAudioOutputPrivate::startTimers()
{
audioBuffer->startFillTimer();
if (intervalTimer->interval() > 0)
intervalTimer->start();
}
void QAudioOutputPrivate::stopTimers()
{
audioBuffer->stopFillTimer();
intervalTimer->stop();
}
void QAudioOutputPrivate::deviceStopped()
{
intervalTimer->stop();
emit stateChanged(stateCode);
}
void QAudioOutputPrivate::inputReady()
{
QMutexLocker lock(&mutex);
if (stateCode == QAudio::IdleState) {
audioThreadStart();
stateCode = QAudio::ActiveState;
errorCode = QAudio::NoError;
QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, Q_ARG(QAudio::State, stateCode));
}
}
OSStatus QAudioOutputPrivate::renderCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData)
{
Q_UNUSED(ioActionFlags)
Q_UNUSED(inTimeStamp)
Q_UNUSED(inBusNumber)
Q_UNUSED(inNumberFrames)
QAudioOutputPrivate* d = static_cast<QAudioOutputPrivate*>(inRefCon);
const int threadState = d->audioThreadState.fetchAndAddAcquire(0);
if (threadState == Stopped) {
ioData->mBuffers[0].mDataByteSize = 0;
d->audioDeviceStop();
}
else {
const UInt32 bytesPerFrame = d->streamFormat.mBytesPerFrame;
qint64 framesRead;
framesRead = d->audioBuffer->readFrames((char*)ioData->mBuffers[0].mData,
ioData->mBuffers[0].mDataByteSize / bytesPerFrame);
if (framesRead > 0) {
ioData->mBuffers[0].mDataByteSize = framesRead * bytesPerFrame;
d->totalFrames += framesRead;
}
else {
ioData->mBuffers[0].mDataByteSize = 0;
if (framesRead == 0) {
if (threadState == Draining)
d->audioDeviceStop();
else
d->audioDeviceIdle();
}
else
d->audioDeviceError();
}
}
return noErr;
}
QT_END_NAMESPACE
#include "qaudiooutput_mac_p.moc"

View File

@@ -0,0 +1,171 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUT_MAC_P_H
#define QAUDIOOUTPUT_MAC_P_H
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <QtCore/qobject.h>
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
#include <qaudio.h>
#include <qaudioformat.h>
#include <qaudiosystem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QIODevice;
class QAbstractAudioDeviceInfo;
namespace QtMultimediaKitInternal
{
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;
QtMultimediaKitInternal::QAudioOutputBuffer* audioBuffer;
QAtomicInt audioThreadState;
QWaitCondition threadFinished;
QMutex mutex;
QTimer* intervalTimer;
QAbstractAudioDeviceInfo *audioDeviceInfo;
QAudio::Error errorCode;
QAudio::State stateCode;
QAudioOutputPrivate(const QByteArray& device);
~QAudioOutputPrivate();
bool open();
void close();
QAudioFormat format() const;
void setFormat(const QAudioFormat& fmt);
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
void audioThreadStart();
void audioThreadStop();
void audioThreadDrain();
void audioDeviceStop();
void audioDeviceIdle();
void audioDeviceError();
void startTimers();
void stopTimers();
private slots:
void deviceStopped();
void inputReady();
private:
enum { Running, Draining, Stopped };
static OSStatus renderCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,713 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudiooutput_symbian_p.h"
QT_BEGIN_NAMESPACE
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const int UnderflowTimerInterval = 50; // ms
//-----------------------------------------------------------------------------
// Private class
//-----------------------------------------------------------------------------
SymbianAudioOutputPrivate::SymbianAudioOutputPrivate(
QAudioOutputPrivate *audioDevice)
: m_audioDevice(audioDevice)
{
}
SymbianAudioOutputPrivate::~SymbianAudioOutputPrivate()
{
}
qint64 SymbianAudioOutputPrivate::readData(char *data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)
return 0;
}
qint64 SymbianAudioOutputPrivate::writeData(const char *data, qint64 len)
{
qint64 totalWritten = 0;
if (m_audioDevice->state() == QAudio::ActiveState ||
m_audioDevice->state() == QAudio::IdleState) {
while (totalWritten < len) {
const qint64 written = m_audioDevice->pushData(data + totalWritten,
len - totalWritten);
if (written > 0)
totalWritten += written;
else
break;
}
}
return totalWritten;
}
//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------
QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device)
: m_device(device)
, m_clientBufferSize(SymbianAudio::DefaultBufferSize)
, m_notifyInterval(SymbianAudio::DefaultNotifyInterval)
, m_notifyTimer(new QTimer(this))
, m_lastNotifyPosition(0)
, m_error(QAudio::NoError)
, m_internalState(SymbianAudio::ClosedState)
, m_externalState(QAudio::StoppedState)
, m_pullMode(false)
, m_source(0)
, m_devSound(0)
, m_devSoundBuffer(0)
, m_devSoundBufferSize(0)
, m_bytesWritten(0)
, m_pushDataReady(false)
, m_bytesPadding(0)
, m_underflow(false)
, m_lastBuffer(false)
, m_underflowTimer(new QTimer(this))
, m_samplesPlayed(0)
, m_totalSamplesPlayed(0)
{
connect(m_notifyTimer.data(), SIGNAL(timeout()),
this, SLOT(notifyTimerExpired()));
m_underflowTimer->setInterval(UnderflowTimerInterval);
connect(m_underflowTimer.data(), SIGNAL(timeout()), this,
SLOT(underflowTimerExpired()));
}
QAudioOutputPrivate::~QAudioOutputPrivate()
{
close();
}
void QAudioOutputPrivate::setFormat(const QAudioFormat& fmt)
{
m_format = fmt;
}
void QAudioOutputPrivate::start(QIODevice *device)
{
stop();
// We have to set these before the call to open() because of the
// logic in initializingState()
m_pullMode = true;
m_source = device;
open();
if (SymbianAudio::ClosedState != m_internalState) {
connect(m_source, SIGNAL(readyRead()), this, SLOT(dataReady()));
m_elapsed.restart();
}
}
QIODevice* QAudioOutputPrivate::start()
{
stop();
open();
if (SymbianAudio::ClosedState != m_internalState) {
m_source = new SymbianAudioOutputPrivate(this);
m_source->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
m_elapsed.restart();
}
return m_source;
}
void QAudioOutputPrivate::stop()
{
close();
}
void QAudioOutputPrivate::reset()
{
#ifndef PRE_S60_52_PLATFORM
int err = m_devSound->flush();
if (err != 0)
setError(QAudio::FatalError);
#else
m_totalSamplesPlayed += getSamplesPlayed();
m_devSound->stop();
m_bytesPadding = 0;
startPlayback();
#endif
}
void QAudioOutputPrivate::suspend()
{
if (SymbianAudio::ActiveState == m_internalState
|| SymbianAudio::IdleState == m_internalState) {
m_underflowTimer->stop();
const qint64 samplesWritten = SymbianAudio::Utils::bytesToSamples(
m_format, m_bytesWritten);
const qint64 samplesPlayed = getSamplesPlayed();
#ifdef PRE_S60_52_PLATFORM
m_totalSamplesPlayed += samplesPlayed;
m_bytesWritten = 0;
#endif
const bool paused = m_devSound->pause();
if (paused) {
setState(SymbianAudio::SuspendedPausedState);
} else {
m_devSoundBuffer = 0;
// Calculate the amount of data dropped
const qint64 paddingSamples = samplesWritten - samplesPlayed;
Q_ASSERT(paddingSamples >= 0);
m_bytesPadding = SymbianAudio::Utils::samplesToBytes(m_format,
paddingSamples);
setState(SymbianAudio::SuspendedStoppedState);
}
}
}
void QAudioOutputPrivate::resume()
{
if (QAudio::SuspendedState == m_externalState) {
if (SymbianAudio::SuspendedPausedState == m_internalState) {
#ifndef PRE_S60_52_PLATFORM
setState(SymbianAudio::ActiveState);
if (m_devSoundBuffer != 0)
devsoundBufferToBeFilled(m_devSoundBuffer);
m_devSound->start();
#else
//defined in else part of macro to enable compatibility of previous code
m_devSound->resume();
#endif
} else {
startPlayback();
}
}
}
int QAudioOutputPrivate::bytesFree() const
{
int result = 0;
if (m_devSoundBuffer) {
const TDes8 &outputBuffer = m_devSoundBuffer->Data();
result = outputBuffer.MaxLength() - outputBuffer.Length();
}
return result;
}
int QAudioOutputPrivate::periodSize() const
{
return bufferSize();
}
void QAudioOutputPrivate::setBufferSize(int value)
{
// Note that DevSound does not allow its client to specify the buffer size.
// This functionality is available via custom interfaces, but since these
// cannot be guaranteed to work across all DevSound implementations, we
// do not use them here.
// In order to comply with the expected bevahiour of QAudioOutput, we store
// the value and return it from bufferSize(), but the underlying DevSound
// buffer size remains unchanged.
if (value > 0)
m_clientBufferSize = value;
}
int QAudioOutputPrivate::bufferSize() const
{
return m_devSoundBufferSize ? m_devSoundBufferSize : m_clientBufferSize;
}
void QAudioOutputPrivate::setNotifyInterval(int ms)
{
if (ms >= 0) {
//const int oldNotifyInterval = m_notifyInterval;
m_notifyInterval = ms;
if (m_notifyInterval && (SymbianAudio::ActiveState == m_internalState ||
SymbianAudio::IdleState == m_internalState))
m_notifyTimer->start(m_notifyInterval);
else
m_notifyTimer->stop();
}
}
int QAudioOutputPrivate::notifyInterval() const
{
return m_notifyInterval;
}
qint64 QAudioOutputPrivate::processedUSecs() const
{
int samplesPlayed = 0;
if (!m_devSound)
return samplesPlayed;
if (QAudio::SuspendedState != m_externalState)
samplesPlayed = getSamplesPlayed();
// Protect against division by zero
Q_ASSERT_X(m_format.frequency() > 0, Q_FUNC_INFO, "Invalid frequency");
#ifndef PRE_S60_52_PLATFORM
const qint64 devSoundSamplesPlayed(m_devSound->samplesProcessed());
const qint64 result = qint64(1000000) *
(devSoundSamplesPlayed)
/ m_format.frequency();
#else
const qint64 result = qint64(1000000) *
(samplesPlayed + m_totalSamplesPlayed)
/ m_format.frequency();
#endif
return result;
}
qint64 QAudioOutputPrivate::elapsedUSecs() const
{
const qint64 result = (QAudio::StoppedState == state()) ?
0 : m_elapsed.elapsed() * 1000;
return result;
}
QAudio::Error QAudioOutputPrivate::error() const
{
return m_error;
}
QAudio::State QAudioOutputPrivate::state() const
{
return m_externalState;
}
QAudioFormat QAudioOutputPrivate::format() const
{
return m_format;
}
//-----------------------------------------------------------------------------
// Private functions
//-----------------------------------------------------------------------------
void QAudioOutputPrivate::notifyTimerExpired()
{
const qint64 pos = processedUSecs();
if (pos > m_lastNotifyPosition) {
int count = (pos - m_lastNotifyPosition) / (m_notifyInterval * 1000);
while (count--) {
emit notify();
m_lastNotifyPosition += m_notifyInterval * 1000;
}
}
}
void QAudioOutputPrivate::dataReady()
{
// Client-provided QIODevice has data ready to read.
Q_ASSERT_X(m_source->bytesAvailable(), Q_FUNC_INFO,
"readyRead signal received, but no data available");
if (!m_bytesPadding)
pullData();
}
void QAudioOutputPrivate::underflowTimerExpired()
{
const TInt samplesPlayed = getSamplesPlayed();
if (m_samplesPlayed && (samplesPlayed == m_samplesPlayed)) {
setError(QAudio::UnderrunError);
#ifndef PRE_S60_52_PLATFORM
m_underflowTimer->stop();
#endif
} else {
m_samplesPlayed = samplesPlayed;
m_underflowTimer->start();
}
}
void QAudioOutputPrivate::devsoundInitializeComplete(int err)
{
Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState,
Q_FUNC_INFO, "Invalid state");
if (!err && m_devSound->isFormatSupported(m_format))
startPlayback();
else
setError(QAudio::OpenError);
}
void QAudioOutputPrivate::devsoundBufferToBeFilled(CMMFBuffer *bufferBase)
{
// Following receipt of this signal, DevSound should not provide another
// buffer until we have returned the current one.
Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held");
// Will be returned to DevSoundWrapper by bufferProcessed().
m_devSoundBuffer = static_cast<CMMFDataBuffer*>(bufferBase);
#ifndef PRE_S60_52_PLATFORM
if (m_externalState == QAudio::SuspendedState) {
// This condition occurs when buffertobefilled callback is received after
// pause command is processed.
return;
}
#endif
if (!m_devSoundBufferSize)
m_devSoundBufferSize = m_devSoundBuffer->Data().MaxLength();
writePaddingData();
if (m_pullMode && isDataReady() && !m_bytesPadding)
pullData();
}
void QAudioOutputPrivate::devsoundPlayError(int err)
{
switch (err) {
case KErrUnderflow:
m_underflow = true;
if (m_pullMode && !m_lastBuffer)
setError(QAudio::UnderrunError);
else
setState(SymbianAudio::IdleState);
break;
case KErrOverflow:
// Silently consume this error when in playback mode
break;
default:
setError(QAudio::IOError);
break;
}
}
void QAudioOutputPrivate::open()
{
Q_ASSERT_X(SymbianAudio::ClosedState == m_internalState,
Q_FUNC_INFO, "DevSound already opened");
Q_ASSERT(!m_devSound);
m_devSound = new SymbianAudio::DevSoundWrapper(QAudio::AudioOutput, this);
connect(m_devSound, SIGNAL(initializeComplete(int)),
this, SLOT(devsoundInitializeComplete(int)));
connect(m_devSound, SIGNAL(bufferToBeProcessed(CMMFBuffer *)),
this, SLOT(devsoundBufferToBeFilled(CMMFBuffer *)));
connect(m_devSound, SIGNAL(processingError(int)),
this, SLOT(devsoundPlayError(int)));
setState(SymbianAudio::InitializingState);
m_devSound->initialize(m_format.codec());
}
void QAudioOutputPrivate::startPlayback()
{
bool ok = m_devSound->setFormat(m_format);
if (ok)
ok = m_devSound->start();
if (ok) {
if (isDataReady())
setState(SymbianAudio::ActiveState);
else
setState(SymbianAudio::IdleState);
if (m_notifyInterval)
m_notifyTimer->start(m_notifyInterval);
m_underflow = false;
Q_ASSERT(m_devSound->samplesProcessed() == 0);
writePaddingData();
if (m_pullMode && m_source->bytesAvailable() && !m_bytesPadding)
dataReady();
} else {
setError(QAudio::OpenError);
close();
}
}
void QAudioOutputPrivate::writePaddingData()
{
// See comments in suspend()
while (m_devSoundBuffer && m_bytesPadding) {
if (SymbianAudio::IdleState == m_internalState)
setState(SymbianAudio::ActiveState);
TDes8 &outputBuffer = m_devSoundBuffer->Data();
const qint64 outputBytes = bytesFree();
const qint64 paddingBytes = outputBytes < m_bytesPadding ?
outputBytes : m_bytesPadding;
unsigned char *ptr = const_cast<unsigned char*>(outputBuffer.Ptr());
Mem::FillZ(ptr, paddingBytes);
outputBuffer.SetLength(outputBuffer.Length() + paddingBytes);
m_bytesPadding -= paddingBytes;
Q_ASSERT(m_bytesPadding >= 0);
if (m_pullMode && m_source->atEnd())
lastBufferFilled();
if ((paddingBytes == outputBytes) || !m_bytesPadding)
bufferFilled();
}
}
qint64 QAudioOutputPrivate::pushData(const char *data, qint64 len)
{
// Data has been written to SymbianAudioOutputPrivate
Q_ASSERT_X(!m_pullMode, Q_FUNC_INFO,
"pushData called when in pull mode");
const unsigned char *const inputPtr =
reinterpret_cast<const unsigned char*>(data);
qint64 bytesWritten = 0;
if (SymbianAudio::IdleState == m_internalState)
setState(SymbianAudio::ActiveState);
while (m_devSoundBuffer && (bytesWritten < len)) {
// writePaddingData() is called from BufferToBeFilled(), so we should
// never have any padding data left at this point.
Q_ASSERT_X(0 == m_bytesPadding, Q_FUNC_INFO,
"Padding bytes remaining in pushData");
TDes8 &outputBuffer = m_devSoundBuffer->Data();
const qint64 outputBytes = bytesFree();
const qint64 inputBytes = len - bytesWritten;
const qint64 copyBytes = outputBytes < inputBytes ?
outputBytes : inputBytes;
outputBuffer.Append(inputPtr + bytesWritten, copyBytes);
bytesWritten += copyBytes;
bufferFilled();
}
m_pushDataReady = (bytesWritten < len);
// If DevSound is still initializing (m_internalState == InitializingState),
// we cannot transition m_internalState to ActiveState, but we must emit
// an (external) state change from IdleState to ActiveState. The following
// call triggers this signal.
setState(m_internalState);
return bytesWritten;
}
void QAudioOutputPrivate::pullData()
{
Q_ASSERT_X(m_pullMode, Q_FUNC_INFO,
"pullData called when in push mode");
// writePaddingData() is called by BufferToBeFilled() before pullData(),
// so we should never have any padding data left at this point.
Q_ASSERT_X(0 == m_bytesPadding, Q_FUNC_INFO,
"Padding bytes remaining in pullData");
qint64 inputBytes = m_source->bytesAvailable();
while (m_devSoundBuffer && inputBytes) {
if (SymbianAudio::IdleState == m_internalState)
setState(SymbianAudio::ActiveState);
TDes8 &outputBuffer = m_devSoundBuffer->Data();
const qint64 outputBytes = bytesFree();
const qint64 copyBytes = outputBytes < inputBytes ?
outputBytes : inputBytes;
char *outputPtr = (char*)(outputBuffer.Ptr() + outputBuffer.Length());
const qint64 bytesCopied = m_source->read(outputPtr, copyBytes);
//Partial buffers can be sent to DevSound. This assert not required.
//Q_ASSERT(bytesCopied == copyBytes);
outputBuffer.SetLength(outputBuffer.Length() + bytesCopied);
inputBytes -= bytesCopied;
if(bytesCopied == 0)
return;
if (m_source->atEnd())
lastBufferFilled();
else
bufferFilled();
}
}
void QAudioOutputPrivate::bufferFilled()
{
Q_ASSERT_X(m_devSoundBuffer, Q_FUNC_INFO, "No buffer to return");
const TDes8 &outputBuffer = m_devSoundBuffer->Data();
m_bytesWritten += outputBuffer.Length();
m_devSoundBuffer = 0;
m_samplesPlayed = getSamplesPlayed();
m_underflowTimer->start();
if (QAudio::UnderrunError == m_error)
m_error = QAudio::NoError;
m_devSound->bufferProcessed();
}
void QAudioOutputPrivate::lastBufferFilled()
{
Q_ASSERT_X(m_devSoundBuffer, Q_FUNC_INFO, "No buffer to fill");
Q_ASSERT_X(!m_lastBuffer, Q_FUNC_INFO, "Last buffer already sent");
m_lastBuffer = true;
m_devSoundBuffer->SetLastBuffer(ETrue);
bufferFilled();
}
void QAudioOutputPrivate::close()
{
m_lastNotifyPosition = 0;
m_underflowTimer->stop();
m_error = QAudio::NoError;
if (m_devSound)
m_devSound->stop();
delete m_devSound;
m_devSound = 0;
m_devSoundBuffer = 0;
m_devSoundBufferSize = 0;
if (!m_pullMode) // m_source is owned
delete m_source;
m_pullMode = false;
m_source = 0;
m_bytesWritten = 0;
m_pushDataReady = false;
m_bytesPadding = 0;
m_underflow = false;
m_lastBuffer = false;
m_samplesPlayed = 0;
m_totalSamplesPlayed = 0;
setState(SymbianAudio::ClosedState);
}
qint64 QAudioOutputPrivate::getSamplesPlayed() const
{
qint64 result = 0;
if (m_devSound) {
const qint64 samplesWritten = SymbianAudio::Utils::bytesToSamples(
m_format, m_bytesWritten);
if (m_underflow) {
result = samplesWritten;
} else {
// This is necessary because some DevSound implementations report
// that they have played more data than has actually been provided to them
// by the client.
const qint64 devSoundSamplesPlayed(m_devSound->samplesProcessed());
result = qMin(devSoundSamplesPlayed, samplesWritten);
}
}
return result;
}
void QAudioOutputPrivate::setError(QAudio::Error error)
{
m_error = error;
// Although no state transition actually occurs here, a stateChanged event
// must be emitted to inform the client that the call to start() was
// unsuccessful.
if (QAudio::OpenError == error) {
emit stateChanged(QAudio::StoppedState);
} else {
if (QAudio::UnderrunError == error)
setState(SymbianAudio::IdleState);
else
// Close the DevSound instance. This causes a transition to
// StoppedState. This must be done asynchronously in case the
// current function was called from a DevSound event handler, in which
// case deleting the DevSound instance may cause an exception.
QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
}
}
void QAudioOutputPrivate::setState(SymbianAudio::State newInternalState)
{
const QAudio::State oldExternalState = m_externalState;
m_internalState = newInternalState;
m_externalState = SymbianAudio::Utils::stateNativeToQt(m_internalState);
if (m_externalState != QAudio::ActiveState &&
m_externalState != QAudio::IdleState)
m_notifyTimer->stop();
if (m_externalState != oldExternalState)
emit stateChanged(m_externalState);
}
bool QAudioOutputPrivate::isDataReady() const
{
return (m_source && m_source->bytesAvailable())
|| m_bytesPadding
|| m_pushDataReady;
}
QT_END_NAMESPACE
#include "moc_qaudiooutput_symbian_p.cpp"

View File

@@ -0,0 +1,201 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUT_SYMBIAN_P_H
#define QAUDIOOUTPUT_SYMBIAN_P_H
#include <qaudiosystem.h>
#include <QTime>
#include <QTimer>
#include <sounddevice.h>
#include "qaudio_symbian_p.h"
QT_BEGIN_NAMESPACE
class QAudioOutputPrivate;
class SymbianAudioOutputPrivate : public QIODevice
{
friend class QAudioOutputPrivate;
Q_OBJECT
public:
SymbianAudioOutputPrivate(QAudioOutputPrivate *audio);
~SymbianAudioOutputPrivate();
qint64 readData(char *data, qint64 len);
qint64 writeData(const char *data, qint64 len);
private:
QAudioOutputPrivate *const m_audioDevice;
};
class QAudioOutputPrivate
: public QAbstractAudioOutput
{
friend class SymbianAudioOutputPrivate;
Q_OBJECT
public:
QAudioOutputPrivate(const QByteArray &device);
~QAudioOutputPrivate();
// QAbstractAudioOutput
void start(QIODevice *device);
QIODevice* start();
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
QAudioFormat format() const;
void setFormat(const QAudioFormat& fmt);
private slots:
void dataReady();
void notifyTimerExpired();
void underflowTimerExpired();
void devsoundInitializeComplete(int err);
void devsoundBufferToBeFilled(CMMFBuffer *);
void devsoundPlayError(int err);
private:
void open();
void startPlayback();
void writePaddingData();
qint64 pushData(const char *data, qint64 len);
void pullData();
void bufferFilled();
void lastBufferFilled();
Q_INVOKABLE void close();
qint64 getSamplesPlayed() const;
void setError(QAudio::Error error);
void setState(SymbianAudio::State state);
bool isDataReady() const;
private:
const QByteArray m_device;
QAudioFormat m_format;
int m_clientBufferSize;
int m_notifyInterval;
QScopedPointer<QTimer> m_notifyTimer;
qint64 m_lastNotifyPosition;
QTime m_elapsed;
QAudio::Error m_error;
SymbianAudio::State m_internalState;
QAudio::State m_externalState;
bool m_pullMode;
QIODevice *m_source;
SymbianAudio::DevSoundWrapper* m_devSound;
// Buffer provided by DevSound, to be filled with data.
CMMFDataBuffer *m_devSoundBuffer;
int m_devSoundBufferSize;
// Number of bytes transferred from QIODevice to QAudioOutput. It is
// necessary to count this because data is dropped when suspend() is
// called. The difference between the position reported by DevSound and
// this value allows us to calculate m_bytesPadding;
quint32 m_bytesWritten;
// True if client has provided data while the audio subsystem was not
// ready to consume it.
bool m_pushDataReady;
// Number of zero bytes which will be written when client calls resume().
quint32 m_bytesPadding;
// True if PlayError(KErrUnderflow) has been called.
bool m_underflow;
// True if a buffer marked with the "last buffer" flag has been provided
// to DevSound.
bool m_lastBuffer;
// Some DevSound implementations ignore all underflow errors raised by the
// audio driver, unless the last buffer flag has been set by the client.
// In push-mode playback, this flag will never be set, so the underflow
// error will never be reported. In order to work around this, a timer
// is used, which gets reset every time the client provides more data. If
// the timer expires, an underflow error is raised by this object.
QScopedPointer<QTimer> m_underflowTimer;
// Result of previous call to CMMFDevSound::SamplesPlayed(). This value is
// used to determine whether, when m_underflowTimer expires, an
// underflow error has actually occurred.
quint32 m_samplesPlayed;
// Samples played up to the last call to suspend(). It is necessary
// to cache this because suspend() is implemented using
// CMMFDevSound::Stop(), which resets DevSound's SamplesPlayed() counter.
quint32 m_totalSamplesPlayed;
};
QT_END_NAMESPACE
#endif

View File

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

View File

@@ -0,0 +1,167 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QAUDIOOUTPUTWIN_H
#define QAUDIOOUTPUTWIN_H
#include <windows.h>
#include <mmsystem.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmutex.h>
#include <qaudio.h>
#include <qaudiodeviceinfo.h>
#include <qaudiosystem.h>
// For compat with 4.6
#if !defined(QT_WIN_CALLBACK)
# if defined(Q_CC_MINGW)
# define QT_WIN_CALLBACK CALLBACK __attribute__ ((force_align_arg_pointer))
# else
# define QT_WIN_CALLBACK CALLBACK
# endif
#endif
QT_BEGIN_NAMESPACE
class QAudioOutputPrivate : public QAbstractAudioOutput
{
Q_OBJECT
public:
QAudioOutputPrivate(const QByteArray &device);
~QAudioOutputPrivate();
qint64 write( const char *data, qint64 len );
void setFormat(const QAudioFormat& fmt);
QAudioFormat format() const;
QIODevice* start();
void start(QIODevice* device);
void stop();
void reset();
void suspend();
void resume();
int bytesFree() const;
int periodSize() const;
void setBufferSize(int value);
int bufferSize() const;
void setNotifyInterval(int milliSeconds);
int notifyInterval() const;
qint64 processedUSecs() const;
qint64 elapsedUSecs() const;
QAudio::Error error() const;
QAudio::State state() const;
QIODevice* audioSource;
QAudioFormat settings;
QAudio::Error errorState;
QAudio::State deviceState;
private slots:
void feedback();
bool deviceReady();
private:
QByteArray m_device;
bool resuming;
int bytesAvailable;
QTime timeStamp;
qint64 elapsedTimeOffset;
QTime timeStampOpened;
qint32 buffer_size;
qint32 period_size;
qint64 totalTimeValue;
bool pullMode;
int intervalTime;
static void QT_WIN_CALLBACK waveOutProc( HWAVEOUT hWaveOut, UINT uMsg,
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
QMutex mutex;
WAVEHDR* allocateBlocks(int size, int count);
void freeBlocks(WAVEHDR* blockArray);
bool open();
void close();
WAVEFORMATEX wfx;
HWAVEOUT hWaveOut;
MMRESULT result;
WAVEHDR header;
WAVEHDR* waveBlocks;
volatile bool finished;
volatile int waveFreeBlockCount;
int waveCurrentBlock;
char* audioBuffer;
};
class OutputPrivate : public QIODevice
{
Q_OBJECT
public:
OutputPrivate(QAudioOutputPrivate* audio);
~OutputPrivate();
qint64 readData( char* data, qint64 len);
qint64 writeData(const char* data, qint64 len);
private:
QAudioOutputPrivate *audioDevice;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,180 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudiosystemplugin.h"
#include "qaudiopluginloader_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtGui/qapplication.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
QAudioPluginLoader::QAudioPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity):
m_iid(iid)
{
m_location = location + "/";
load();
}
QAudioPluginLoader::~QAudioPluginLoader()
{
for (int i = 0; i < m_plugins.count(); i++ ) {
delete m_plugins.at(i);
}
}
QStringList QAudioPluginLoader::pluginList() const
{
#if !defined QT_NO_DEBUG
const bool showDebug = qgetenv("QT_DEBUG_PLUGINS").toInt() > 0;
#endif
QStringList paths = QApplication::libraryPaths();
#ifdef QTM_PLUGIN_PATH
paths << QLatin1String(QTM_PLUGIN_PATH);
#endif
#if !defined QT_NO_DEBUG
if (showDebug)
qDebug() << "Plugin paths:" << paths;
#endif
//temp variable to avoid multiple identic path
QSet<QString> processed;
/* Discover a bunch o plugins */
QStringList plugins;
/* Enumerate our plugin paths */
for (int i=0; i < paths.count(); i++) {
if (processed.contains(paths.at(i)))
continue;
processed.insert(paths.at(i));
QDir pluginsDir(paths.at(i)+m_location);
if (!pluginsDir.exists())
continue;
QStringList files = pluginsDir.entryList(QDir::Files);
#if !defined QT_NO_DEBUG
if (showDebug)
qDebug()<<"Looking for plugins in "<<pluginsDir.path()<<files;
#endif
for (int j=0; j < files.count(); j++) {
const QString &file = files.at(j);
#if defined(Q_WS_MAEMO_5)
if (!file.contains(QLatin1String("n900audio")))
#endif
plugins << pluginsDir.absoluteFilePath(file);
}
}
return plugins;
}
QStringList QAudioPluginLoader::keys() const
{
QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
QStringList list;
for (int i = 0; i < m_plugins.count(); i++) {
QAudioSystemPlugin* p = qobject_cast<QAudioSystemPlugin*>(m_plugins.at(i)->instance());
if (p) list << p->keys();
}
return list;
}
QObject* QAudioPluginLoader::instance(QString const &key)
{
QMutexLocker locker(&m_mutex);
for (int i = 0; i < m_plugins.count(); i++) {
QAudioSystemPlugin* p = qobject_cast<QAudioSystemPlugin*>(m_plugins.at(i)->instance());
if (p && p->keys().contains(key))
return m_plugins.at(i)->instance();
}
return 0;
}
QList<QObject*> QAudioPluginLoader::instances(QString const &key)
{
QMutexLocker locker(&m_mutex);
QList<QObject*> list;
for (int i = 0; i < m_plugins.count(); i++) {
QAudioSystemPlugin* p = qobject_cast<QAudioSystemPlugin*>(m_plugins.at(i)->instance());
if (p && p->keys().contains(key))
list << m_plugins.at(i)->instance();
}
return list;
}
void QAudioPluginLoader::load()
{
if (!m_plugins.isEmpty())
return;
#if !defined QT_NO_DEBUG
const bool showDebug = qgetenv("QT_DEBUG_PLUGINS").toInt() > 0;
#endif
QStringList plugins = pluginList();
for (int i=0; i < plugins.count(); i++) {
QPluginLoader* loader = new QPluginLoader(plugins.at(i));
QObject *o = loader->instance();
if (o != 0 && o->qt_metacast(m_iid) != 0) {
m_plugins.append(loader);
} else {
#if !defined QT_NO_DEBUG
if (showDebug)
qWarning() << "QAudioPluginLoader: Failed to load plugin: "
<< plugins.at(i) << loader->errorString();
#endif
delete o;
//we are not calling loader->unload here for it may cause problem on some device
delete loader;
}
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIOPLUGINLOADER_H
#define QAUDIOPLUGINLOADER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <qmobilityglobal.h>
#include <QObject>
#include <QtCore/qstring.h>
#include <QtCore/qmap.h>
#include <QtCore/qmutex.h>
#include <QtCore/qpluginloader.h>
QT_BEGIN_NAMESPACE
class QAudioPluginLoader
{
public:
QAudioPluginLoader(const char *iid,
const QString &suffix = QString(),
Qt::CaseSensitivity = Qt::CaseSensitive);
~QAudioPluginLoader();
QStringList keys() const;
QObject* instance(QString const &key);
QList<QObject*> instances(QString const &key);
private:
QStringList pluginList() const;
void load();
QMutex m_mutex;
QByteArray m_iid;
QString m_location;
QList<QPluginLoader*> m_plugins;
};
QT_END_NAMESPACE
#endif // QAUDIOPLUGINLOADER_H

View File

@@ -0,0 +1,423 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudiosystem.h"
QT_BEGIN_NAMESPACE
/*!
\class QAbstractAudioDeviceInfo
\brief The QAbstractAudioDeviceInfo class is a base class for audio backends.
\ingroup multimedia
\inmodule QtMultimediaKit
\internal
\since 1.0
This class implements the audio functionality for
QAudioDeviceInfo, i.e., QAudioDeviceInfo keeps a
QAbstractAudioDeviceInfo and routes function calls to it. For a
description of the functionality that QAbstractAudioDeviceInfo
implements, you can read the class and functions documentation of
QAudioDeviceInfo.
\sa QAudioDeviceInfo
\sa QAbstractAudioOutput, QAbstractAudioInput
*/
/*!
\fn virtual QAudioFormat QAbstractAudioDeviceInfo::preferredFormat() const
Returns the recommended settings to use.
\since 1.0
*/
/*!
\fn virtual bool QAbstractAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
Returns true if \a format is available from audio device.
\since 1.0
*/
/*!
\fn virtual QString QAbstractAudioDeviceInfo::deviceName() const
Returns the audio device name.
\since 1.0
*/
/*!
\fn virtual QStringList QAbstractAudioDeviceInfo::supportedCodecs()
Returns the list of currently available codecs.
\since 1.0
*/
/*!
\fn virtual QList<int> QAbstractAudioDeviceInfo::supportedSampleRates()
Returns the list of currently available sample rates.
\since 1.0
*/
/*!
\fn virtual QList<int> QAbstractAudioDeviceInfo::supportedChannelCounts()
Returns the list of currently available channels.
\since 1.0
*/
/*!
\fn virtual QList<int> QAbstractAudioDeviceInfo::supportedSampleSizes()
Returns the list of currently available sample sizes.
\since 1.0
*/
/*!
\fn virtual QList<QAudioFormat::Endian> QAbstractAudioDeviceInfo::supportedByteOrders()
Returns the list of currently available byte orders.
\since 1.0
*/
/*!
\fn virtual QList<QAudioFormat::SampleType> QAbstractAudioDeviceInfo::supportedSampleTypes()
Returns the list of currently available sample types.
\since 1.0
*/
/*!
\class QAbstractAudioOutput
\brief The QAbstractAudioOutput class is a base class for audio backends.
\since 1.0
\ingroup multimedia
\inmodule QtMultimediaKit
\internal
QAbstractAudioOutput implements audio functionality for
QAudioOutput, i.e., QAudioOutput routes function calls to
QAbstractAudioOutput. For a description of the functionality that
is implemented, see the QAudioOutput class and function
descriptions.
\sa QAudioOutput
*/
/*!
\fn virtual void QAbstractAudioOutput::start(QIODevice* device)
Uses the \a device as the QIODevice to transfer data.
\since 1.0
*/
/*!
\fn virtual QIODevice* QAbstractAudioOutput::start()
Returns a pointer to the QIODevice being used to handle
the data transfer. This QIODevice can be used to write() audio data directly.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::stop()
Stops the audio output.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::reset()
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::suspend()
Stops processing audio data, preserving buffered audio data.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::resume()
Resumes processing audio data after a suspend()
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::bytesFree() const
Returns the free space available in bytes in the audio buffer.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::periodSize() const
Returns the period size in bytes.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setBufferSize(int value)
Sets the audio buffer size to \a value in bytes.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::bufferSize() const
Returns the audio buffer size in bytes.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setNotifyInterval(int ms)
Sets the interval for notify() signal to be emitted. This is based on the \a ms
of audio data processed not on actual real-time. The resolution of the timer
is platform specific.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioOutput::notifyInterval() const
Returns the notify interval in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioOutput::processedUSecs() const
Returns the amount of audio data processed since start() was called in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioOutput::elapsedUSecs() const
Returns the milliseconds since start() was called, including time in Idle and suspend states.
\since 1.0
*/
/*!
\fn virtual QAudio::Error QAbstractAudioOutput::error() const
Returns the error state.
\since 1.0
*/
/*!
\fn virtual QAudio::State QAbstractAudioOutput::state() const
Returns the state of audio processing.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioOutput::setFormat(const QAudioFormat& fmt)
Set the QAudioFormat to use to \a fmt.
Setting the format is only allowable while in QAudio::StoppedState.
\since 1.0
*/
/*!
\fn virtual QAudioFormat QAbstractAudioOutput::format() const
Returns the QAudioFormat being used.
\since 1.0
*/
/*!
\fn QAbstractAudioOutput::errorChanged(QAudio::Error error)
This signal is emitted when the \a error state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioOutput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioOutput::notify()
This signal is emitted when x ms of audio data has been processed
the interval set by setNotifyInterval(x).
\since 1.0
*/
/*!
\class QAbstractAudioInput
\brief The QAbstractAudioInput class provides access for QAudioInput to access the audio
device provided by the plugin.
\since 1.0
\ingroup multimedia
\inmodule QtMultimediaKit
\internal
QAudioDeviceInput keeps an instance of QAbstractAudioInput and
routes calls to functions of the same name to QAbstractAudioInput.
This means that it is QAbstractAudioInput that implements the
audio functionality. For a description of the functionality, see
the QAudioInput class description.
\sa QAudioInput
*/
/*!
\fn virtual void QAbstractAudioInput::start(QIODevice* device)
Uses the \a device as the QIODevice to transfer data.
\since 1.0
*/
/*!
\fn virtual QIODevice* QAbstractAudioInput::start()
Returns a pointer to the QIODevice being used to handle
the data transfer. This QIODevice can be used to read() audio data directly.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::stop()
Stops the audio input.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::reset()
Drops all audio data in the buffers, resets buffers to zero.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::suspend()
Stops processing audio data, preserving buffered audio data.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::resume()
Resumes processing audio data after a suspend().
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::bytesReady() const
Returns the amount of audio data available to read in bytes.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::periodSize() const
Returns the period size in bytes.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::setBufferSize(int value)
Sets the audio buffer size to \a value in milliseconds.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::bufferSize() const
Returns the audio buffer size in milliseconds.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::setNotifyInterval(int ms)
Sets the interval for notify() signal to be emitted. This is based
on the \a ms of audio data processed not on actual real-time.
The resolution of the timer is platform specific.
\since 1.0
*/
/*!
\fn virtual int QAbstractAudioInput::notifyInterval() const
Returns the notify interval in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioInput::processedUSecs() const
Returns the amount of audio data processed since start() was called in milliseconds.
\since 1.0
*/
/*!
\fn virtual qint64 QAbstractAudioInput::elapsedUSecs() const
Returns the milliseconds since start() was called, including time in Idle and suspend states.
\since 1.0
*/
/*!
\fn virtual QAudio::Error QAbstractAudioInput::error() const
Returns the error state.
\since 1.0
*/
/*!
\fn virtual QAudio::State QAbstractAudioInput::state() const
Returns the state of audio processing.
\since 1.0
*/
/*!
\fn virtual void QAbstractAudioInput::setFormat(const QAudioFormat& fmt)
Set the QAudioFormat to use to \a fmt.
Setting the format is only allowable while in QAudio::StoppedState.
\since 1.0
*/
/*!
\fn virtual QAudioFormat QAbstractAudioInput::format() const
Returns the QAudioFormat being used
\since 1.0
*/
/*!
\fn QAbstractAudioInput::errorChanged(QAudio::Error error)
This signal is emitted when the \a error state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioInput::stateChanged(QAudio::State state)
This signal is emitted when the device \a state has changed.
\since 1.0
*/
/*!
\fn QAbstractAudioInput::notify()
This signal is emitted when x ms of audio data has been processed
the interval set by setNotifyInterval(x).
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudiosystem.cpp"

View File

@@ -0,0 +1,136 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIOSYSTEM_H
#define QAUDIOSYSTEM_H
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include "qaudio.h"
#include "qaudioformat.h"
#include "qaudiodeviceinfo.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class Q_MULTIMEDIA_EXPORT QAbstractAudioDeviceInfo : public QObject
{
Q_OBJECT
public:
virtual QAudioFormat preferredFormat() const = 0;
virtual bool isFormatSupported(const QAudioFormat &format) const = 0;
virtual QString deviceName() const = 0;
virtual QStringList supportedCodecs() = 0;
virtual QList<int> supportedSampleRates() = 0;
virtual QList<int> supportedChannelCounts() = 0;
virtual QList<int> supportedSampleSizes() = 0;
virtual QList<QAudioFormat::Endian> supportedByteOrders() = 0;
virtual QList<QAudioFormat::SampleType> supportedSampleTypes() = 0;
};
class Q_MULTIMEDIA_EXPORT QAbstractAudioOutput : public QObject
{
Q_OBJECT
public:
virtual void start(QIODevice *device) = 0;
virtual QIODevice* start() = 0;
virtual void stop() = 0;
virtual void reset() = 0;
virtual void suspend() = 0;
virtual void resume() = 0;
virtual int bytesFree() const = 0;
virtual int periodSize() const = 0;
virtual void setBufferSize(int value) = 0;
virtual int bufferSize() const = 0;
virtual void setNotifyInterval(int milliSeconds) = 0;
virtual int notifyInterval() const = 0;
virtual qint64 processedUSecs() const = 0;
virtual qint64 elapsedUSecs() const = 0;
virtual QAudio::Error error() const = 0;
virtual QAudio::State state() const = 0;
virtual void setFormat(const QAudioFormat& fmt) = 0;
virtual QAudioFormat format() const = 0;
Q_SIGNALS:
void errorChanged(QAudio::Error);
void stateChanged(QAudio::State);
void notify();
};
class Q_MULTIMEDIA_EXPORT QAbstractAudioInput : public QObject
{
Q_OBJECT
public:
virtual void start(QIODevice *device) = 0;
virtual QIODevice* start() = 0;
virtual void stop() = 0;
virtual void reset() = 0;
virtual void suspend() = 0;
virtual void resume() = 0;
virtual int bytesReady() const = 0;
virtual int periodSize() const = 0;
virtual void setBufferSize(int value) = 0;
virtual int bufferSize() const = 0;
virtual void setNotifyInterval(int milliSeconds) = 0;
virtual int notifyInterval() const = 0;
virtual qint64 processedUSecs() const = 0;
virtual qint64 elapsedUSecs() const = 0;
virtual QAudio::Error error() const = 0;
virtual QAudio::State state() const = 0;
virtual void setFormat(const QAudioFormat& fmt) = 0;
virtual QAudioFormat format() const = 0;
Q_SIGNALS:
void errorChanged(QAudio::Error);
void stateChanged(QAudio::State);
void notify();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOSYSTEM_H

View File

@@ -0,0 +1,143 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qaudiosystemplugin.h"
QT_BEGIN_NAMESPACE
/*!
\class QAudioSystemPlugin
\brief The QAudioSystemPlugin class provides an abstract base for audio plugins.
\since 1.0
\ingroup multimedia
\inmodule QtMultimediaKit
\internal
Writing a audio plugin is achieved by subclassing this base class,
reimplementing the pure virtual functions keys(), availableDevices(),
createInput(), createOutput() and createDeviceInfo() then exporting
the class with the Q_EXPORT_PLUGIN2() macro.
Unit tests are available to help in debugging new plugins.
\sa QAbstractAudioDeviceInfo, QAbstractAudioOutput, QAbstractAudioInput
Qt supports win32, linux(alsa) and Mac OS X standard (builtin to the
QtMultimediaKit library at compile time).
You can support other backends other than these predefined ones by
creating a plugin subclassing QAudioSystemPlugin, QAbstractAudioDeviceInfo,
QAbstractAudioOutput and QAbstractAudioInput.
Add "default" to your list of keys() available to override the default
audio device to be provided by your plugin.
-audio-backend configure option will force compiling in of the builtin backend
into the QtMultimediaKit library at compile time. This is automatic by default
and will only be compiled into the library if the dependencies are installed.
eg. alsa-devel package installed for linux.
If the builtin backend is not compiled into the QtMultimediaKit library and
no audio plugins are available a fallback dummy backend will be used.
This should print out warnings if this is the case when you try and use QAudioInput or QAudioOutput. To fix this problem
reconfigure Qt using -audio-backend or create your own plugin with a default
key to always override the dummy fallback. The easiest way to determine
if you have only a dummy backend is to get a list of available audio devices.
QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).size() = 0 (dummy backend)
*/
/*!
Construct a new audio plugin with \a parent.
This is invoked automatically by the Q_EXPORT_PLUGIN2() macro.
*/
QAudioSystemPlugin::QAudioSystemPlugin(QObject* parent) :
QObject(parent)
{}
/*!
Destroy the audio plugin
You never have to call this explicitly. Qt destroys a plugin automatically when it is no longer used.
*/
QAudioSystemPlugin::~QAudioSystemPlugin()
{}
/*!
\fn QStringList QAudioSystemPlugin::keys() const
Returns the list of device identifiers this plugin supports.
\since 1.0
*/
/*!
\fn QList<QByteArray> QAudioSystemPlugin::availableDevices(QAudio::Mode mode) const
Returns a list of available audio devices for \a mode
\since 1.0
*/
/*!
\fn QAbstractAudioInput* QAudioSystemPlugin::createInput(const QByteArray& device)
Returns a pointer to a QAbstractAudioInput created using \a device identifier
\since 1.0
*/
/*!
\fn QAbstractAudioOutput* QAudioSystemPlugin::createOutput(const QByteArray& device)
Returns a pointer to a QAbstractAudioOutput created using \a device identifier
\since 1.0
*/
/*!
\fn QAbstractAudioDeviceInfo* QAudioSystemPlugin::createDeviceInfo(const QByteArray& device, QAudio::Mode mode)
Returns a pointer to a QAbstractAudioDeviceInfo created using \a device and \a mode
\since 1.0
*/
QT_END_NAMESPACE
#include "moc_qaudiosystemplugin.cpp"

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QAUDIOSYSTEMPLUGIN_H
#define QAUDIOSYSTEMPLUGIN_H
#include <QtCore/qstring.h>
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <qmobilityglobal.h>
#include <qtmedianamespace.h>
#include "qaudioformat.h"
#include "qaudiodeviceinfo.h"
#include "qaudiosystem.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
struct Q_MULTIMEDIA_EXPORT QAudioSystemFactoryInterface : public QFactoryInterface
{
virtual QList<QByteArray> availableDevices(QAudio::Mode) const = 0;
virtual QAbstractAudioInput* createInput(const QByteArray& device) = 0;
virtual QAbstractAudioOutput* createOutput(const QByteArray& device) = 0;
virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0;
};
#define QAudioSystemFactoryInterface_iid \
"com.nokia.qt.QAudioSystemFactoryInterface"
Q_DECLARE_INTERFACE(QAudioSystemFactoryInterface, QAudioSystemFactoryInterface_iid)
class Q_MULTIMEDIA_EXPORT QAudioSystemPlugin : public QObject, public QAudioSystemFactoryInterface
{
Q_OBJECT
Q_INTERFACES(QAudioSystemFactoryInterface:QFactoryInterface)
public:
QAudioSystemPlugin(QObject *parent = 0);
~QAudioSystemPlugin();
virtual QStringList keys() const = 0;
virtual QList<QByteArray> availableDevices(QAudio::Mode) const = 0;
virtual QAbstractAudioInput* createInput(const QByteArray& device) = 0;
virtual QAbstractAudioOutput* createOutput(const QByteArray& device) = 0;
virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QAUDIOSYSTEMPLUGIN_H

View File

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

View File

@@ -0,0 +1,398 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsamplecache_p.h"
#include "qwavedecoder_p.h"
#include <QtNetwork>
//#define QT_SAMPLECACHE_DEBUG
QT_BEGIN_NAMESPACE
/*!
\class QSampleCache
\internal
When you want to get a sound sample data, you need to request the QSample reference from QSampleCache.
\since 1.1
\code
QSample *m_sample; // class member.
private Q_SLOTS:
void decoderError();
void sampleReady();
\endcode
\code
Q_GLOBAL_STATIC(QSampleCache, sampleCache) //declare a singleton manager
\endcode
\code
m_sample = sampleCache()->requestSample(url);
switch(m_sample->state()) {
case QSample::Ready:
sampleReady();
break;
case QSample::Error:
decoderError();
break;
default:
connect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
connect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
break;
}
\endcode
When you no longer need the sound sample data, you need to release it:
\code
if (m_sample) {
m_sample->release();
m_sample = 0;
}
\endcode
*/
QSampleCache::QSampleCache()
: m_networkAccessManager(0)
, m_mutex(QMutex::Recursive)
, m_capacity(0)
, m_usage(0)
{
m_loadingThread.setObjectName(QLatin1String("QSampleCache::LoadingThread"));
}
QNetworkAccessManager& QSampleCache::networkAccessManager()
{
if (!m_networkAccessManager)
m_networkAccessManager = new QNetworkAccessManager();
return *m_networkAccessManager;
}
QSampleCache::~QSampleCache()
{
QMutexLocker m(&m_mutex);
m_loadingThread.quit();
m_loadingThread.wait();
// Killing the loading thread means that no samples can be
// deleted using deleteLater. And some samples that had deleteLater
// already called won't have been processed (m_staleSamples)
foreach (QSample* sample, m_samples)
delete sample;
foreach (QSample* sample, m_staleSamples)
delete sample; // deleting a sample does affect the m_staleSamples list, but foreach copies it
delete m_networkAccessManager;
}
QSample* QSampleCache::requestSample(const QUrl& url)
{
if (!m_loadingThread.isRunning())
m_loadingThread.start();
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: request sample [" << url << "]";
#endif
QMutexLocker locker(&m_mutex);
QMap<QUrl, QSample*>::iterator it = m_samples.find(url);
QSample* sample;
if (it == m_samples.end()) {
sample = new QSample(url, this);
m_samples.insert(url, sample);
sample->moveToThread(&m_loadingThread);
} else {
sample = *it;
}
sample->addRef();
locker.unlock();
sample->loadIfNecessary();
return sample;
}
void QSampleCache::setCapacity(qint64 capacity)
{
QMutexLocker locker(&m_mutex);
if (m_capacity == capacity)
return;
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: capacity changes from " << m_capacity << "to " << capacity;
#endif
if (m_capacity > 0 && capacity <= 0) { //memory management strategy changed
for (QMap<QUrl, QSample*>::iterator it = m_samples.begin(); it != m_samples.end();) {
QSample* sample = *it;
if (sample->m_ref == 0) {
unloadSample(sample);
it = m_samples.erase(it);
} else
it++;
}
}
m_capacity = capacity;
refresh(0);
}
// Called locked
void QSampleCache::unloadSample(QSample *sample)
{
m_usage -= sample->m_soundData.size();
m_staleSamples.insert(sample);
sample->deleteLater();
}
// Called in both threads
void QSampleCache::refresh(qint64 usageChange)
{
QMutexLocker locker(&m_mutex);
m_usage += usageChange;
if (m_capacity <= 0 || m_usage <= m_capacity)
return;
#ifdef QT_SAMPLECACHE_DEBUG
qint64 recoveredSize = 0;
#endif
//free unused samples to keep usage under capacity limit.
for (QMap<QUrl, QSample*>::iterator it = m_samples.begin(); it != m_samples.end();) {
QSample* sample = *it;
if (sample->m_ref > 0) {
++it;
continue;
}
#ifdef QT_SAMPLECACHE_DEBUG
recoveredSize += sample->m_soundData.size();
#endif
unloadSample(sample);
it = m_samples.erase(it);
if (m_usage <= m_capacity)
return;
}
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSampleCache: refresh(" << usageChange
<< ") recovered size =" << recoveredSize
<< "new usage =" << m_usage;
#endif
if (m_usage > m_capacity)
qWarning() << "QSampleCache: usage[" << m_usage << " out of limit[" << m_capacity << "]";
}
// Called in both threads
void QSampleCache::removeUnreferencedSample(QSample *sample)
{
QMutexLocker m(&m_mutex);
m_staleSamples.remove(sample);
}
// Called in loader thread (since this lives in that thread)
// Also called from application thread after loader thread dies.
QSample::~QSample()
{
// Remove ourselves from our parent
m_parent->removeUnreferencedSample(this);
QMutexLocker locker(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "~QSample" << this << ": deleted [" << m_url << "]" << QThread::currentThread();
#endif
cleanup();
}
// Called in application thread
void QSample::loadIfNecessary()
{
QMutexLocker locker(&m_mutex);
if (m_state == QSample::Error || m_state == QSample::Creating) {
m_state = QSample::Loading;
QMetaObject::invokeMethod(this, "load", Qt::QueuedConnection);
}
}
// Called in both threads
bool QSampleCache::notifyUnreferencedSample(QSample* sample)
{
QMutexLocker locker(&m_mutex);
if (m_capacity > 0)
return false;
m_samples.remove(sample->m_url);
m_staleSamples.insert(sample);
sample->deleteLater();
return true;
}
// Called in application threadd
void QSample::release()
{
QMutexLocker locker(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "Sample:: release" << this << QThread::currentThread() << m_ref;
#endif
m_ref--;
if (m_ref == 0)
m_parent->notifyUnreferencedSample(this);
}
// Called in dtor and when stream is loaded
// must be called locked.
void QSample::cleanup()
{
delete m_waveDecoder;
delete m_stream;
m_waveDecoder = 0;
m_stream = 0;
}
// Called in application thread
void QSample::addRef()
{
m_ref++;
}
// Called in loading thread
void QSample::readSample()
{
Q_ASSERT(QThread::currentThread()->objectName() == "QSampleCache::LoadingThread");
QMutexLocker m(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: readSample";
#endif
qint64 read = m_waveDecoder->read(m_soundData.data() + m_sampleReadLength,
qMin(m_waveDecoder->bytesAvailable(),
qint64(m_waveDecoder->size() - m_sampleReadLength)));
if (read > 0)
m_sampleReadLength += read;
if (m_sampleReadLength < m_waveDecoder->size())
return;
Q_ASSERT(m_sampleReadLength == qint64(m_soundData.size()));
onReady();
}
// Called in loading thread
void QSample::decoderReady()
{
Q_ASSERT(QThread::currentThread()->objectName() == "QSampleCache::LoadingThread");
QMutexLocker m(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: decoder ready";
#endif
m_parent->refresh(m_waveDecoder->size());
m_soundData.resize(m_waveDecoder->size());
m_sampleReadLength = 0;
qint64 read = m_waveDecoder->read(m_soundData.data(), m_waveDecoder->size());
if (read > 0)
m_sampleReadLength += read;
if (m_sampleReadLength >= m_waveDecoder->size())
onReady();
}
// Called in all threads
QSample::State QSample::state() const
{
QMutexLocker m(&m_mutex);
return m_state;
}
// Called in loading thread
// Essentially a second ctor, doesn't need locks (?)
void QSample::load()
{
Q_ASSERT(QThread::currentThread()->objectName() == "QSampleCache::LoadingThread");
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: load [" << m_url << "]";
#endif
m_stream = m_parent->networkAccessManager().get(QNetworkRequest(m_url));
connect(m_stream, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(decoderError()));
m_waveDecoder = new QWaveDecoder(m_stream);
connect(m_waveDecoder, SIGNAL(formatKnown()), SLOT(decoderReady()));
connect(m_waveDecoder, SIGNAL(invalidFormat()), SLOT(decoderError()));
connect(m_waveDecoder, SIGNAL(readyRead()), SLOT(readSample()));
}
// Called in loading thread
void QSample::decoderError()
{
Q_ASSERT(QThread::currentThread()->objectName() == "QSampleCache::LoadingThread");
QMutexLocker m(&m_mutex);
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: decoder error";
#endif
cleanup();
m_state = QSample::Error;
emit error();
}
// Called in loading thread from decoder when sample is done. Locked already.
void QSample::onReady()
{
Q_ASSERT(QThread::currentThread()->objectName() == "QSampleCache::LoadingThread");
#ifdef QT_SAMPLECACHE_DEBUG
qDebug() << "QSample: load ready";
#endif
m_audioFormat = m_waveDecoder->audioFormat();
cleanup();
m_state = QSample::Ready;
emit ready();
}
// Called in application thread, then moved to loader thread
QSample::QSample(const QUrl& url, QSampleCache *parent)
: m_parent(parent)
, m_stream(0)
, m_waveDecoder(0)
, m_url(url)
, m_sampleReadLength(0)
, m_state(Creating)
, m_ref(0)
{
}
QT_END_NAMESPACE
#include "moc_qsamplecache_p.cpp"

View File

@@ -0,0 +1,158 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSAMPLECACHE_P_H
#define QSAMPLECACHE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qobject.h>
#include <QtCore/qthread.h>
#include <QtCore/qurl.h>
#include <QtCore/qmutex.h>
#include <QtCore/qmap.h>
#include <QtCore/qset.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QNetworkAccessManager;
class QSampleCache;
class QWaveDecoder;
// Lives in application thread
class QSample : public QObject
{
Q_OBJECT
public:
friend class QSampleCache;
enum State
{
Creating,
Loading,
Error,
Ready,
};
State state() const;
// These are not (currently) locked because they are only meant to be called after these
// variables are updated to their final states
const QByteArray& data() const { Q_ASSERT(state() == Ready); return m_soundData; }
const QAudioFormat& format() const { Q_ASSERT(state() == Ready); return m_audioFormat; }
void release();
Q_SIGNALS:
void error();
void ready();
protected:
QSample(const QUrl& url, QSampleCache *parent);
private Q_SLOTS:
void load();
void decoderError();
void readSample();
void decoderReady();
private:
void onReady();
void cleanup();
void addRef();
void loadIfNecessary();
QSample();
~QSample();
mutable QMutex m_mutex;
QSampleCache *m_parent;
QByteArray m_soundData;
QAudioFormat m_audioFormat;
QIODevice *m_stream;
QWaveDecoder *m_waveDecoder;
QUrl m_url;
qint64 m_sampleReadLength;
State m_state;
int m_ref;
};
class QSampleCache
{
public:
friend class QSample;
QSampleCache();
~QSampleCache();
QSample* requestSample(const QUrl& url);
void setCapacity(qint64 capacity);
private:
QMap<QUrl, QSample*> m_samples;
QSet<QSample*> m_staleSamples;
QNetworkAccessManager *m_networkAccessManager;
QMutex m_mutex;
qint64 m_capacity;
qint64 m_usage;
QThread m_loadingThread;
QNetworkAccessManager& networkAccessManager();
void refresh(qint64 usageChange);
bool notifyUnreferencedSample(QSample* sample);
void removeUnreferencedSample(QSample* sample);
void unloadSample(QSample* sample);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSAMPLECACHE_P_H

View File

@@ -0,0 +1,301 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsoundeffect_p.h"
#if defined(QT_MULTIMEDIA_PULSEAUDIO)
#include "qsoundeffect_pulse_p.h"
#elif(QT_MULTIMEDIA_QMEDIAPLAYER)
#include "qsoundeffect_qmedia_p.h"
#else
#include "qsoundeffect_qsound_p.h"
#endif
QT_BEGIN_NAMESPACE
/*!
\qmlclass SoundEffect QSoundEffect
\brief The SoundEffect element provides a way to play sound effects in QML.
\since 1.0
\inmodule QtMultimediaKit
This element is part of the \bold{QtMultimediaKit 1.1} module.
The following example plays a WAV file on mouse click.
\snippet doc/src/snippets/multimedia-snippets/soundeffect.qml complete snippet
*/
/*!
\qmlproperty url SoundEffect::source
\since 1.0
This property provides a way to control the sound to play.
*/
/*!
\qmlproperty int SoundEffect::loops
\since 1.0
This property provides a way to control the number of times to repeat the sound on each play().
Set to -1 (infinite) to enable infinite loop.
*/
/*!
\qmlproperty qreal SoundEffect::volume
\since 1.0
This property holds the volume of the playback, from 0.0 (silent) to 1.0 (maximum volume).
Note: Currently this has no effect on Mac OS X and Symbian.
*/
/*!
\qmlproperty bool SoundEffect::muted
\since 1.0
This property provides a way to control muting.
*/
/*!
\qmlproperty bool SoundEffect::playing
\since 1.1
This property indicates if the soundeffect is playing or not.
*/
/*!
\qmlproperty int SoundEffect::status
\since 1.0
This property indicates the following status of the soundeffect.
Null: no source has been set or is null.
Loading: the soundeffect is trying to load the source.
Ready: the source is loaded and ready for play.
Error: some error happened during operation, such as failure of loading the source.
*/
/*!
\qmlsignal SoundEffect::sourceChanged()
\since 1.0
This handler is called when the source has changed.
*/
/*!
\qmlsignal SoundEffect::loopsChanged()
\since 1.0
This handler is called when the number of loops has changed.
*/
/*!
\qmlsignal SoundEffect::volumeChanged()
\since 1.0
This handler is called when the volume has changed.
*/
/*!
\qmlsignal SoundEffect::mutedChanged()
\since 1.0
This handler is called when the mute state has changed.
*/
/*!
\qmlsignal SoundEffect::playingChanged()
\since 1.0
This handler is called when the playing property has changed.
*/
/*!
\qmlsignal SoundEffect::statusChanged()
This handler is called when the status property has changed.
\since 1.0
*/
/*!
\internal
\since 1.0
*/
QSoundEffect::QSoundEffect(QObject *parent) :
QObject(parent)
{
d = new QSoundEffectPrivate(this);
connect(d, SIGNAL(volumeChanged()), SIGNAL(volumeChanged()));
connect(d, SIGNAL(mutedChanged()), SIGNAL(mutedChanged()));
connect(d, SIGNAL(loadedChanged()), SIGNAL(loadedChanged()));
connect(d, SIGNAL(playingChanged()), SIGNAL(playingChanged()));
connect(d, SIGNAL(statusChanged()), SIGNAL(statusChanged()));
}
QSoundEffect::~QSoundEffect()
{
d->deleteLater();
}
QStringList QSoundEffect::supportedMimeTypes()
{
return QSoundEffectPrivate::supportedMimeTypes();
}
QUrl QSoundEffect::source() const
{
return d->source();
}
void QSoundEffect::setSource(const QUrl &url)
{
if (d->source() == url)
return;
d->setSource(url);
emit sourceChanged();
}
int QSoundEffect::loopCount() const
{
return d->loopCount();
}
void QSoundEffect::setLoopCount(int loopCount)
{
if (loopCount < 0 && loopCount != Infinite) {
qWarning("SoundEffect: loops should be SoundEffect.Infinite, 0 or positive integer");
return;
}
if (loopCount == 0)
loopCount = 1;
if (d->loopCount() == loopCount)
return;
d->setLoopCount(loopCount);
emit loopCountChanged();
}
qreal QSoundEffect::volume() const
{
return qreal(d->volume()) / 100;
}
void QSoundEffect::setVolume(qreal volume)
{
if (volume < 0 || volume > 1) {
qWarning("SoundEffect: volume should be between 0.0 and 1.0");
return;
}
int iVolume = qRound(volume * 100);
if (d->volume() == iVolume)
return;
d->setVolume(iVolume);
}
bool QSoundEffect::isMuted() const
{
return d->isMuted();
}
void QSoundEffect::setMuted(bool muted)
{
if (d->isMuted() == muted)
return;
d->setMuted(muted);
}
bool QSoundEffect::isLoaded() const
{
return d->isLoaded();
}
/*!
\qmlmethod SoundEffect::play()
Start playback of the sound effect, looping the effect for the number of
times as specificed in the loops property.
This is the default method for SoundEffect.
\snippet doc/src/snippets/multimedia-snippets/soundeffect.qml play sound on click
\since 1.0
*/
void QSoundEffect::play()
{
d->play();
}
bool QSoundEffect::isPlaying() const
{
return d->isPlaying();
}
QSoundEffect::Status QSoundEffect::status() const
{
return d->status();
}
/*!
\qmlmethod SoundEffect::stop()
Stop current playback.
Note that if the backend is PulseAudio, due to the limitation of the underlying API,
tis stop will only prevent next looping but will not be able to stop current playback immediately.
\since 1.0
*/
void QSoundEffect::stop()
{
d->stop();
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_p.cpp"

View File

@@ -0,0 +1,140 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_P_H
#define QSOUNDEFFECT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <qmobilityglobal.h>
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QSoundEffectPrivate;
class Q_MULTIMEDIA_EXPORT QSoundEffect : public QObject
{
Q_OBJECT
Q_CLASSINFO("DefaultMethod", "play()")
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
Q_PROPERTY(bool playing READ isPlaying NOTIFY playingChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_ENUMS(Loop)
Q_ENUMS(Status)
public:
enum Loop
{
Infinite = -2,
};
enum Status
{
Null,
Loading,
Ready,
Error
};
explicit QSoundEffect(QObject *parent = 0);
~QSoundEffect();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
qreal volume() const;
void setVolume(qreal volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying() const;
Status status() const;
Q_SIGNALS:
void sourceChanged();
void loopCountChanged();
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
public Q_SLOTS:
void play();
void stop();
private:
Q_DISABLE_COPY(QSoundEffect)
QSoundEffectPrivate* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_H

View File

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

View File

@@ -0,0 +1,160 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_PULSE_H
#define QSOUNDEFFECT_PULSE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qsoundeffect_p.h"
#include <QtCore/qobject.h>
#include <QtCore/qdatetime.h>
#include <qmediaplayer.h>
#include <pulse/pulseaudio.h>
#include "qsamplecache_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QSoundEffectPrivate : public QObject
{
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying() const;
QSoundEffect::Status status() const;
public Q_SLOTS:
void play();
void stop();
Q_SIGNALS:
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
private Q_SLOTS:
void decoderError();
void sampleReady();
void uploadSample();
void contextReady();
void underRun();
void prepare();
void streamReady();
void emptyComplete();
void updateVolume();
void updateMuted();
private:
void playSample();
void emptyStream();
void createPulseStream();
void unloadPulseStream();
void setPlaying(bool playing);
void setStatus(QSoundEffect::Status status);
static void stream_write_callback(pa_stream *s, size_t length, void *userdata);
static void stream_state_callback(pa_stream *s, void *userdata);
static void stream_underrun_callback(pa_stream *s, void *userdata);
static void stream_cork_callback(pa_stream *s, int success, void *userdata);
static void stream_flush_callback(pa_stream *s, int success, void *userdata);
static void stream_write_done_callback(void *p);
static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata);
static void stream_reset_buffer_callback(pa_stream *s, int success, void *userdata);
static void setvolume_callback(pa_context *c, int success, void *userdata);
static void setmuted_callback(pa_context *c, int success, void *userdata);
pa_stream *m_pulseStream;
int m_sinkInputId;
pa_sample_spec m_pulseSpec;
int m_pulseBufferSize;
bool m_emptying;
bool m_sampleReady;
bool m_playing;
QSoundEffect::Status m_status;
bool m_muted;
bool m_playQueued;
bool m_stopping;
int m_volume;
int m_loopCount;
int m_runningCount;
QUrl m_source;
QByteArray m_name;
QSample *m_sample;
int m_position;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_PULSE_H

View File

@@ -0,0 +1,233 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qsoundeffect_qmedia_p.h"
#include <QtCore/qcoreapplication.h>
#include "qmediacontent.h"
#include "qmediaplayer.h"
QT_BEGIN_NAMESPACE
QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
QObject(parent),
m_loopCount(1),
m_runningCount(0),
m_player(0),
m_status(QSoundEffect::Null),
m_playing(false)
{
m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency);
connect(m_player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(stateChanged(QMediaPlayer::State)));
connect(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
connect(m_player, SIGNAL(error(QMediaPlayer::Error)), SLOT(error(QMediaPlayer::Error)));
connect(m_player, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged()));
connect(m_player, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged()));
}
QSoundEffectPrivate::~QSoundEffectPrivate()
{
}
QStringList QSoundEffectPrivate::supportedMimeTypes()
{
return QMediaPlayer::supportedMimeTypes();
}
QUrl QSoundEffectPrivate::source() const
{
return m_player->media().canonicalUrl();
}
void QSoundEffectPrivate::setSource(const QUrl &url)
{
m_player->setMedia(url);
}
int QSoundEffectPrivate::loopCount() const
{
return m_loopCount;
}
void QSoundEffectPrivate::setLoopCount(int loopCount)
{
m_loopCount = loopCount;
}
int QSoundEffectPrivate::volume() const
{
return m_player->volume();
}
void QSoundEffectPrivate::setVolume(int volume)
{
m_player->setVolume(volume);
}
bool QSoundEffectPrivate::isMuted() const
{
return m_player->isMuted();
}
void QSoundEffectPrivate::setMuted(bool muted)
{
m_player->setMuted(muted);
}
bool QSoundEffectPrivate::isLoaded() const
{
return m_status == QSoundEffect::Ready;
}
bool QSoundEffectPrivate::isPlaying() const
{
return m_playing;
}
QSoundEffect::Status QSoundEffectPrivate::status() const
{
return m_status;
}
void QSoundEffectPrivate::play()
{
if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error)
return;
if (m_loopCount < 0) {
m_runningCount = -1;
}
else {
if (m_runningCount < 0)
m_runningCount = 0;
m_runningCount += m_loopCount;
}
m_player->play();
}
void QSoundEffectPrivate::stop()
{
m_runningCount = 0;
m_player->stop();
}
void QSoundEffectPrivate::stateChanged(QMediaPlayer::State state)
{
if (state == QMediaPlayer::StoppedState) {
if (m_runningCount < 0) {
m_player->play();
} else if (m_runningCount == 0) {
setPlaying(false);
return;
} else if (--m_runningCount > 0) {
m_player->play();
} else {
setPlaying(false);
}
} else {
setPlaying(true);
}
}
void QSoundEffectPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
switch(status) {
case QMediaPlayer::LoadingMedia:
setStatus(QSoundEffect::Loading);
break;
case QMediaPlayer::NoMedia:
setStatus(QSoundEffect::Null);
break;
case QMediaPlayer::InvalidMedia:
setStatus(QSoundEffect::Error);
break;
default:
setStatus(QSoundEffect::Ready);
break;
}
}
void QSoundEffectPrivate::error(QMediaPlayer::Error err)
{
bool playingDirty = false;
if (m_playing) {
m_playing = false;
playingDirty = true;
}
setStatus(QSoundEffect::Error);
if (playingDirty)
emit playingChanged();
}
void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
{
if (m_status == status)
return;
bool oldLoaded = isLoaded();
m_status = status;
emit statusChanged();
if (oldLoaded != isLoaded())
emit loadedChanged();
}
void QSoundEffectPrivate::setPlaying(bool playing)
{
if (m_playing == playing)
return;
m_playing = playing;
emit playingChanged();
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_qmedia_p.cpp"

View File

@@ -0,0 +1,119 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_QMEDIA_H
#define QSOUNDEFFECT_QMEDIA_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include "qmediaplayer.h"
#include "qsoundeffect_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QSoundEffectPrivate : public QObject
{
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying() const;
QSoundEffect::Status status() const;
public Q_SLOTS:
void play();
void stop();
Q_SIGNALS:
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
private Q_SLOTS:
void stateChanged(QMediaPlayer::State);
void mediaStatusChanged(QMediaPlayer::MediaStatus);
void error(QMediaPlayer::Error);
private:
void setStatus(QSoundEffect::Status status);
void setPlaying(bool playing);
int m_loopCount;
int m_runningCount;
bool m_playing;
QSoundEffect::Status m_status;
QMediaPlayer *m_player;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_QMEDIA_H

View File

@@ -0,0 +1,222 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// INTERNAL USE ONLY: Do NOT use for any other purpose.
//
#include "qsoundeffect_qsound_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtGui/qsound.h>
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
QObject(parent),
m_playing(false),
m_timerID(0),
m_muted(false),
m_loopCount(1),
m_volume(100),
m_status(QSoundEffect::Null),
m_sound(0)
{
if (!QSound::isAvailable())
qWarning("SoundEffect(qsound) : not available");
}
QSoundEffectPrivate::~QSoundEffectPrivate()
{
}
QStringList QSoundEffectPrivate::supportedMimeTypes()
{
QStringList supportedTypes;
supportedTypes << QLatin1String("audio/x-wav") << QLatin1String("audio/vnd.wave") ;
return supportedTypes;
}
QUrl QSoundEffectPrivate::source() const
{
return m_source;
}
void QSoundEffectPrivate::setSource(const QUrl &url)
{
if (url.isEmpty()) {
m_source = QUrl();
setStatus(QSoundEffect::Null);
return;
}
if (url.scheme() != QLatin1String("file")) {
m_source = url;
setStatus(QSoundEffect::Error);
return;
}
if (m_sound != 0)
delete m_sound;
m_source = url;
m_sound = new QSound(m_source.toLocalFile(), this);
m_sound->setLoops(m_loopCount);
m_status = QSoundEffect::Ready;
emit statusChanged();
emit loadedChanged();
}
int QSoundEffectPrivate::loopCount() const
{
return m_loopCount;
}
void QSoundEffectPrivate::setLoopCount(int lc)
{
m_loopCount = lc;
if (m_sound)
m_sound->setLoops(lc);
}
int QSoundEffectPrivate::volume() const
{
return m_volume;
}
void QSoundEffectPrivate::setVolume(int v)
{
m_volume = v;
}
bool QSoundEffectPrivate::isMuted() const
{
return m_muted;
}
void QSoundEffectPrivate::setMuted(bool muted)
{
m_muted = muted;
}
bool QSoundEffectPrivate::isLoaded() const
{
return m_status == QSoundEffect::Ready;
}
void QSoundEffectPrivate::play()
{
if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error)
return;
if (m_timerID != 0)
killTimer(m_timerID);
m_timerID = startTimer(500);
m_sound->play();
setPlaying(true);
}
void QSoundEffectPrivate::stop()
{
if (m_timerID != 0)
killTimer(m_timerID);
m_timerID = 0;
m_sound->stop();
setPlaying(false);
}
bool QSoundEffectPrivate::isPlaying()
{
if (m_playing && m_sound && m_sound->isFinished()) {
if (m_timerID != 0)
killTimer(m_timerID);
m_timerID = 0;
setPlaying(false);
}
return m_playing;
}
QSoundEffect::Status QSoundEffectPrivate::status() const
{
return m_status;
}
void QSoundEffectPrivate::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event);
setPlaying(!m_sound->isFinished());
if (isPlaying())
return;
killTimer(m_timerID);
m_timerID = 0;
}
void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
{
if (m_status == status)
return;
bool oldLoaded = isLoaded();
m_status = status;
emit statusChanged();
if (oldLoaded != isLoaded())
emit loadedChanged();
}
void QSoundEffectPrivate::setPlaying(bool playing)
{
if (m_playing == playing)
return;
m_playing = playing;
emit playingChanged();
}
QT_END_NAMESPACE
#include "moc_qsoundeffect_qsound_p.cpp"

View File

@@ -0,0 +1,118 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSOUNDEFFECT_QSOUND_H
#define QSOUNDEFFECT_QSOUND_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include "qsoundeffect_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QSound;
class QSoundEffectPrivate : public QObject
{
Q_OBJECT
public:
explicit QSoundEffectPrivate(QObject* parent);
~QSoundEffectPrivate();
static QStringList supportedMimeTypes();
QUrl source() const;
void setSource(const QUrl &url);
int loopCount() const;
void setLoopCount(int loopCount);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
bool isLoaded() const;
bool isPlaying();
QSoundEffect::Status status() const;
public Q_SLOTS:
void play();
void stop();
Q_SIGNALS:
void volumeChanged();
void mutedChanged();
void loadedChanged();
void playingChanged();
void statusChanged();
private:
void setStatus(QSoundEffect::Status status);
void setPlaying(bool playing);
void timerEvent(QTimerEvent *event);
bool m_playing;
int m_timerID;
bool m_muted;
int m_loopCount;
int m_volume;
QSoundEffect::Status m_status;
QSound *m_sound;
QUrl m_source;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSOUNDEFFECT_QSOUND_H

View File

@@ -0,0 +1,232 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwavedecoder_p.h"
#include <QtCore/qtimer.h>
#include <QtCore/qendian.h>
QT_BEGIN_NAMESPACE
QWaveDecoder::QWaveDecoder(QIODevice *s, QObject *parent):
QIODevice(parent),
haveFormat(false),
dataSize(0),
remaining(0),
source(s),
state(QWaveDecoder::InitialState)
{
open(QIODevice::ReadOnly | QIODevice::Unbuffered);
if (enoughDataAvailable())
QTimer::singleShot(0, this, SLOT(handleData()));
else
connect(source, SIGNAL(readyRead()), SLOT(handleData()));
}
QWaveDecoder::~QWaveDecoder()
{
}
QAudioFormat QWaveDecoder::audioFormat() const
{
return format;
}
int QWaveDecoder::duration() const
{
return size() * 1000 / (format.sampleSize() / 8) / format.channels() / format.frequency();
}
qint64 QWaveDecoder::size() const
{
return haveFormat ? dataSize : 0;
}
bool QWaveDecoder::isSequential() const
{
return source->isSequential();
}
qint64 QWaveDecoder::bytesAvailable() const
{
return haveFormat ? source->bytesAvailable() : 0;
}
qint64 QWaveDecoder::readData(char *data, qint64 maxlen)
{
return haveFormat ? source->read(data, maxlen) : 0;
}
qint64 QWaveDecoder::writeData(const char *data, qint64 len)
{
Q_UNUSED(data);
Q_UNUSED(len);
return -1;
}
void QWaveDecoder::handleData()
{
if (state == QWaveDecoder::InitialState) {
if (source->bytesAvailable() < qint64(sizeof(RIFFHeader)))
return;
RIFFHeader riff;
source->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader));
if (qstrncmp(riff.descriptor.id, "RIFF", 4) != 0 ||
qstrncmp(riff.type, "WAVE", 4) != 0) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
emit invalidFormat();
return;
} else {
state = QWaveDecoder::WaitingForFormatState;
}
}
if (state == QWaveDecoder::WaitingForFormatState) {
if (findChunk("fmt ")) {
chunk descriptor;
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (source->bytesAvailable() < qint64(descriptor.size + sizeof(chunk)))
return;
WAVEHeader wave;
source->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader));
if (descriptor.size > sizeof(WAVEHeader))
discardBytes(descriptor.size - sizeof(WAVEHeader));
if (wave.audioFormat != 0 && wave.audioFormat != 1) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
emit invalidFormat();
return;
} else {
int bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
format.setCodec(QLatin1String("audio/pcm"));
format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setFrequency(qFromLittleEndian<quint32>(wave.sampleRate));
format.setSampleSize(bps);
format.setChannels(qFromLittleEndian<quint16>(wave.numChannels));
state = QWaveDecoder::WaitingForDataState;
}
}
}
if (state == QWaveDecoder::WaitingForDataState) {
if (findChunk("data")) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
chunk descriptor;
source->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
dataSize = descriptor.size;
haveFormat = true;
connect(source, SIGNAL(readyRead()), SIGNAL(readyRead()));
emit formatKnown();
return;
}
}
if (source->atEnd()) {
source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData()));
emit invalidFormat();
return;
}
}
bool QWaveDecoder::enoughDataAvailable()
{
if (source->bytesAvailable() < qint64(sizeof(chunk)))
return false;
chunk descriptor;
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (source->bytesAvailable() < qint64(sizeof(chunk) + descriptor.size))
return false;
return true;
}
bool QWaveDecoder::findChunk(const char *chunkId)
{
if (source->bytesAvailable() < qint64(sizeof(chunk)))
return false;
chunk descriptor;
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (qstrncmp(descriptor.id, chunkId, 4) == 0)
return true;
while (source->bytesAvailable() >= qint64(sizeof(chunk) + descriptor.size)) {
discardBytes(sizeof(chunk) + descriptor.size);
source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
if (qstrncmp(descriptor.id, chunkId, 4) == 0)
return true;
}
return false;
}
void QWaveDecoder::discardBytes(qint64 numBytes)
{
if (source->isSequential())
source->read(numBytes);
else
source->seek(source->pos() + numBytes);
}
QT_END_NAMESPACE
#include "moc_qwavedecoder_p.cpp"

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef WAVEDECODER_H
#define WAVEDECODER_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qiodevice.h>
#include <qaudioformat.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QWaveDecoder : public QIODevice
{
Q_OBJECT
public:
explicit QWaveDecoder(QIODevice *source, QObject *parent = 0);
~QWaveDecoder();
QAudioFormat audioFormat() const;
int duration() const;
qint64 size() const;
bool isSequential() const;
qint64 bytesAvailable() const;
Q_SIGNALS:
void formatKnown();
void invalidFormat();
private Q_SLOTS:
void handleData();
private:
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
bool enoughDataAvailable();
bool findChunk(const char *chunkId);
void discardBytes(qint64 numBytes);
enum State {
InitialState,
WaitingForFormatState,
WaitingForDataState
};
struct chunk
{
char id[4];
quint32 size;
};
struct RIFFHeader
{
chunk descriptor;
char type[4];
};
struct WAVEHeader
{
chunk descriptor;
quint16 audioFormat;
quint16 numChannels;
quint32 sampleRate;
quint32 byteRate;
quint16 blockAlign;
quint16 bitsPerSample;
};
bool haveFormat;
qint64 dataSize;
qint64 remaining;
QAudioFormat format;
QIODevice *source;
State state;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // WAVEDECODER_H

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