Initial copy of QtMultimediaKit.
Comes from original repo, with SHA1: 2c82d5611655e5967f5c5095af50c0991c4378b2
This commit is contained in:
19
src/harmattaninstalls/README
Normal file
19
src/harmattaninstalls/README
Normal 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
92
src/harmattaninstalls/api
Normal 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
|
||||
|
||||
178
src/harmattaninstalls/changelog
Normal file
178
src/harmattaninstalls/changelog
Normal 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
|
||||
|
||||
1
src/harmattaninstalls/compat
Normal file
1
src/harmattaninstalls/compat
Normal file
@@ -0,0 +1 @@
|
||||
5
|
||||
716
src/harmattaninstalls/control
Normal file
716
src/harmattaninstalls/control
Normal 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.
|
||||
2
src/harmattaninstalls/docs
Normal file
2
src/harmattaninstalls/docs
Normal file
@@ -0,0 +1,2 @@
|
||||
INSTALL.txt
|
||||
LGPL_EXCEPTION.txt
|
||||
13
src/harmattaninstalls/libqtm-contacts-tests.aegis
Normal file
13
src/harmattaninstalls/libqtm-contacts-tests.aegis
Normal 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>
|
||||
1
src/harmattaninstalls/libqtm-doc.install
Normal file
1
src/harmattaninstalls/libqtm-doc.install
Normal file
@@ -0,0 +1 @@
|
||||
usr/doc/html/* usr/share/qt4/QtMobility/doc/html
|
||||
54
src/harmattaninstalls/libqtm-examples.aegis
Normal file
54
src/harmattaninstalls/libqtm-examples.aegis
Normal 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>
|
||||
100
src/harmattaninstalls/libqtm-examples.install
Normal file
100
src/harmattaninstalls/libqtm-examples.install
Normal 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
|
||||
145
src/harmattaninstalls/libqtm-multimedia-dev.install
Normal file
145
src/harmattaninstalls/libqtm-multimedia-dev.install
Normal 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
|
||||
32
src/harmattaninstalls/libqtm-multimedia-tests.install
Normal file
32
src/harmattaninstalls/libqtm-multimedia-tests.install
Normal 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
|
||||
8
src/harmattaninstalls/libqtm-multimedia.install
Normal file
8
src/harmattaninstalls/libqtm-multimedia.install
Normal 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
|
||||
10
src/harmattaninstalls/libqtm-systeminfo-tests.aegis
Normal file
10
src/harmattaninstalls/libqtm-systeminfo-tests.aegis
Normal 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>
|
||||
0
src/harmattaninstalls/patches/series
Normal file
0
src/harmattaninstalls/patches/series
Normal file
110
src/harmattaninstalls/rules
Executable file
110
src/harmattaninstalls/rules
Executable 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
|
||||
|
||||
201
src/harmattaninstalls/tests/install_tests
Executable file
201
src/harmattaninstalls/tests/install_tests
Executable 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
|
||||
11
src/harmattaninstalls/tests/testset.txt
Normal file
11
src/harmattaninstalls/tests/testset.txt
Normal 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>
|
||||
2
src/harmattaninstalls/tests/testsuite_footer.txt
Normal file
2
src/harmattaninstalls/tests/testsuite_footer.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
</suite>
|
||||
</testdefinition>
|
||||
4
src/harmattaninstalls/tests/testsuite_header.txt
Normal file
4
src/harmattaninstalls/tests/testsuite_header.txt
Normal 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
5
src/imports/imports.pro
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += multimedia
|
||||
|
||||
85
src/imports/multimedia/multimedia.cpp
Normal file
85
src/imports/multimedia/multimedia.cpp
Normal 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));
|
||||
|
||||
41
src/imports/multimedia/multimedia.pro
Normal file
41
src/imports/multimedia/multimedia.pro
Normal 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
|
||||
}
|
||||
698
src/imports/multimedia/qdeclarativeaudio.cpp
Normal file
698
src/imports/multimedia/qdeclarativeaudio.cpp
Normal 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"
|
||||
|
||||
|
||||
178
src/imports/multimedia/qdeclarativeaudio_p.h
Normal file
178
src/imports/multimedia/qdeclarativeaudio_p.h
Normal 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
|
||||
1342
src/imports/multimedia/qdeclarativecamera.cpp
Normal file
1342
src/imports/multimedia/qdeclarativecamera.cpp
Normal file
File diff suppressed because it is too large
Load Diff
302
src/imports/multimedia/qdeclarativecamera_p.h
Normal file
302
src/imports/multimedia/qdeclarativecamera_p.h
Normal 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
|
||||
97
src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp
Normal file
97
src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp
Normal 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
|
||||
76
src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h
Normal file
76
src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h
Normal 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
|
||||
567
src/imports/multimedia/qdeclarativemediabase.cpp
Normal file
567
src/imports/multimedia/qdeclarativemediabase.cpp
Normal 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
|
||||
|
||||
187
src/imports/multimedia/qdeclarativemediabase_p.h
Normal file
187
src/imports/multimedia/qdeclarativemediabase_p.h
Normal 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
|
||||
185
src/imports/multimedia/qdeclarativemediametadata_p.h
Normal file
185
src/imports/multimedia/qdeclarativemediametadata_p.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
951
src/imports/multimedia/qdeclarativevideo.cpp
Normal file
951
src/imports/multimedia/qdeclarativevideo.cpp
Normal 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"
|
||||
202
src/imports/multimedia/qdeclarativevideo_p.h
Normal file
202
src/imports/multimedia/qdeclarativevideo_p.h
Normal 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
|
||||
1
src/imports/multimedia/qmldir
Normal file
1
src/imports/multimedia/qmldir
Normal file
@@ -0,0 +1 @@
|
||||
plugin declarative_multimedia
|
||||
38
src/imports/qimportbase.pri
Normal file
38
src/imports/qimportbase.pri
Normal 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)
|
||||
}
|
||||
40
src/meegoinstalls/Makefile
Normal file
40
src/meegoinstalls/Makefile
Normal 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
95
src/meegoinstalls/README
Normal 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 )
|
||||
1360
src/meegoinstalls/qt-mobility.spec
Normal file
1360
src/meegoinstalls/qt-mobility.spec
Normal file
File diff suppressed because it is too large
Load Diff
353
src/meegoinstalls/qt-mobility.yaml
Normal file
353
src/meegoinstalls/qt-mobility.yaml
Normal 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.
|
||||
79
src/multimediakit/audio/audio.pri
Normal file
79
src/multimediakit/audio/audio.pri
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/multimediakit/audio/qaudio.cpp
Normal file
103
src/multimediakit/audio/qaudio.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
|
||||
71
src/multimediakit/audio/qaudio.h
Normal file
71
src/multimediakit/audio/qaudio.h
Normal 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
|
||||
145
src/multimediakit/audio/qaudio_mac.cpp
Normal file
145
src/multimediakit/audio/qaudio_mac.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
|
||||
|
||||
142
src/multimediakit/audio/qaudio_mac_p.h
Normal file
142
src/multimediakit/audio/qaudio_mac_p.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
|
||||
|
||||
663
src/multimediakit/audio/qaudio_symbian_p.cpp
Normal file
663
src/multimediakit/audio/qaudio_symbian_p.cpp
Normal 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
|
||||
|
||||
|
||||
204
src/multimediakit/audio/qaudio_symbian_p.h
Normal file
204
src/multimediakit/audio/qaudio_symbian_p.h
Normal 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
|
||||
292
src/multimediakit/audio/qaudiodevicefactory.cpp
Normal file
292
src/multimediakit/audio/qaudiodevicefactory.cpp
Normal 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
|
||||
|
||||
97
src/multimediakit/audio/qaudiodevicefactory_p.h
Normal file
97
src/multimediakit/audio/qaudiodevicefactory_p.h
Normal 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
|
||||
|
||||
487
src/multimediakit/audio/qaudiodeviceinfo.cpp
Normal file
487
src/multimediakit/audio/qaudiodeviceinfo.cpp
Normal 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
|
||||
|
||||
113
src/multimediakit/audio/qaudiodeviceinfo.h
Normal file
113
src/multimediakit/audio/qaudiodeviceinfo.h
Normal 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
|
||||
535
src/multimediakit/audio/qaudiodeviceinfo_alsa_p.cpp
Normal file
535
src/multimediakit/audio/qaudiodeviceinfo_alsa_p.cpp
Normal file
@@ -0,0 +1,535 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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( ¶ms );
|
||||
snd_pcm_hw_params_any( handle, params );
|
||||
|
||||
// set the values!
|
||||
snd_pcm_hw_params_set_channels(handle,params,format.channels());
|
||||
snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
|
||||
|
||||
err = -1;
|
||||
|
||||
switch(format.sampleSize()) {
|
||||
case 8:
|
||||
if(format.sampleType() == QAudioFormat::SignedInt)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
|
||||
else if(format.sampleType() == QAudioFormat::UnSignedInt)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
|
||||
break;
|
||||
case 16:
|
||||
if(format.sampleType() == QAudioFormat::SignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
|
||||
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if(format.sampleType() == QAudioFormat::SignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
|
||||
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
|
||||
}
|
||||
}
|
||||
|
||||
// For now, just accept only audio/pcm codec
|
||||
if(!format.codec().startsWith(QLatin1String("audio/pcm"))) {
|
||||
err=-1;
|
||||
} else
|
||||
testCodec = true;
|
||||
|
||||
if(err>=0 && format.channels() != -1) {
|
||||
err = snd_pcm_hw_params_test_channels(handle,params,format.channels());
|
||||
if(err>=0)
|
||||
err = snd_pcm_hw_params_set_channels(handle,params,format.channels());
|
||||
if(err>=0)
|
||||
testChannel = true;
|
||||
}
|
||||
|
||||
if(err>=0 && format.frequency() != -1) {
|
||||
err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0);
|
||||
if(err>=0)
|
||||
err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
|
||||
if(err>=0)
|
||||
testFreq = true;
|
||||
}
|
||||
|
||||
if((err>=0 && format.sampleSize() != -1) &&
|
||||
(format.sampleType() != QAudioFormat::Unknown)) {
|
||||
switch(format.sampleSize()) {
|
||||
case 8:
|
||||
if(format.sampleType() == QAudioFormat::SignedInt)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
|
||||
else if(format.sampleType() == QAudioFormat::UnSignedInt)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
|
||||
break;
|
||||
case 16:
|
||||
if(format.sampleType() == QAudioFormat::SignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
|
||||
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if(format.sampleType() == QAudioFormat::SignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
|
||||
} else if(format.sampleType() == QAudioFormat::UnSignedInt) {
|
||||
if(format.byteOrder() == QAudioFormat::LittleEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
|
||||
else if(format.byteOrder() == QAudioFormat::BigEndian)
|
||||
err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
|
||||
}
|
||||
}
|
||||
if(err>=0) {
|
||||
testSize = true;
|
||||
testType = true;
|
||||
}
|
||||
}
|
||||
if(err>=0)
|
||||
err = snd_pcm_hw_params(handle, params);
|
||||
|
||||
if(err == 0) {
|
||||
// settings work
|
||||
// close()
|
||||
if(handle)
|
||||
snd_pcm_close(handle);
|
||||
return true;
|
||||
}
|
||||
if(handle)
|
||||
snd_pcm_close(handle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QAudioDeviceInfoInternal::updateLists()
|
||||
{
|
||||
// redo all lists based on current settings
|
||||
freqz.clear();
|
||||
channelz.clear();
|
||||
sizez.clear();
|
||||
byteOrderz.clear();
|
||||
typez.clear();
|
||||
codecz.clear();
|
||||
|
||||
if(!handle)
|
||||
open();
|
||||
|
||||
if(!handle)
|
||||
return;
|
||||
|
||||
for(int i=0; i<(int)MAX_SAMPLE_RATES; i++) {
|
||||
//if(snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0)
|
||||
freqz.append(SAMPLE_RATES[i]);
|
||||
}
|
||||
channelz.append(1);
|
||||
channelz.append(2);
|
||||
if (surround40) channelz.append(4);
|
||||
if (surround51) channelz.append(6);
|
||||
if (surround71) channelz.append(8);
|
||||
sizez.append(8);
|
||||
sizez.append(16);
|
||||
sizez.append(32);
|
||||
byteOrderz.append(QAudioFormat::LittleEndian);
|
||||
byteOrderz.append(QAudioFormat::BigEndian);
|
||||
typez.append(QAudioFormat::SignedInt);
|
||||
typez.append(QAudioFormat::UnSignedInt);
|
||||
typez.append(QAudioFormat::Float);
|
||||
codecz.append(QLatin1String("audio/pcm"));
|
||||
close();
|
||||
}
|
||||
|
||||
QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
|
||||
{
|
||||
QList<QByteArray> allDevices;
|
||||
QList<QByteArray> devices;
|
||||
QByteArray filter;
|
||||
|
||||
#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
|
||||
// Create a list of all current audio devices that support mode
|
||||
void **hints, **n;
|
||||
char *name, *descr, *io;
|
||||
|
||||
if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
|
||||
qWarning() << "no alsa devices available";
|
||||
return devices;
|
||||
}
|
||||
n = hints;
|
||||
|
||||
if(mode == QAudio::AudioInput) {
|
||||
filter = "Input";
|
||||
} else {
|
||||
filter = "Output";
|
||||
}
|
||||
|
||||
while (*n != NULL) {
|
||||
name = snd_device_name_get_hint(*n, "NAME");
|
||||
if (name != 0 && qstrcmp(name, "null") != 0) {
|
||||
descr = snd_device_name_get_hint(*n, "DESC");
|
||||
io = snd_device_name_get_hint(*n, "IOID");
|
||||
|
||||
if ((descr != NULL) && ((io == NULL) || (io == filter))) {
|
||||
QString deviceName = QLatin1String(name);
|
||||
QString deviceDescription = QLatin1String(descr);
|
||||
allDevices.append(deviceName.toLocal8Bit().constData());
|
||||
if (deviceDescription.contains(QLatin1String("Default Audio Device")))
|
||||
devices.append(deviceName.toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
free(name);
|
||||
if (descr != NULL)
|
||||
free(descr);
|
||||
if (io != NULL)
|
||||
free(io);
|
||||
}
|
||||
++n;
|
||||
}
|
||||
snd_device_name_free_hint(hints);
|
||||
|
||||
if(devices.size() > 0) {
|
||||
devices.append("default");
|
||||
}
|
||||
#else
|
||||
int idx = 0;
|
||||
char* name;
|
||||
|
||||
while(snd_card_get_name(idx,&name) == 0) {
|
||||
devices.append(name);
|
||||
idx++;
|
||||
}
|
||||
if (idx > 0)
|
||||
devices.append("default");
|
||||
#endif
|
||||
#if (!defined(Q_WS_MAEMO_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
|
||||
121
src/multimediakit/audio/qaudiodeviceinfo_alsa_p.h
Normal file
121
src/multimediakit/audio/qaudiodeviceinfo_alsa_p.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
|
||||
351
src/multimediakit/audio/qaudiodeviceinfo_mac_p.cpp
Normal file
351
src/multimediakit/audio/qaudiodeviceinfo_mac_p.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
|
||||
96
src/multimediakit/audio/qaudiodeviceinfo_mac_p.h
Normal file
96
src/multimediakit/audio/qaudiodeviceinfo_mac_p.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
235
src/multimediakit/audio/qaudiodeviceinfo_symbian_p.cpp
Normal file
235
src/multimediakit/audio/qaudiodeviceinfo_symbian_p.cpp
Normal 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"
|
||||
|
||||
116
src/multimediakit/audio/qaudiodeviceinfo_symbian_p.h
Normal file
116
src/multimediakit/audio/qaudiodeviceinfo_symbian_p.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
471
src/multimediakit/audio/qaudiodeviceinfo_win32_p.cpp
Normal file
471
src/multimediakit/audio/qaudiodeviceinfo_win32_p.cpp
Normal 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
|
||||
112
src/multimediakit/audio/qaudiodeviceinfo_win32_p.h
Normal file
112
src/multimediakit/audio/qaudiodeviceinfo_win32_p.h
Normal 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
|
||||
407
src/multimediakit/audio/qaudioformat.cpp
Normal file
407
src/multimediakit/audio/qaudioformat.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
|
||||
106
src/multimediakit/audio/qaudioformat.h
Normal file
106
src/multimediakit/audio/qaudioformat.h
Normal 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
|
||||
426
src/multimediakit/audio/qaudioinput.cpp
Normal file
426
src/multimediakit/audio/qaudioinput.cpp
Normal 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"
|
||||
|
||||
111
src/multimediakit/audio/qaudioinput.h
Normal file
111
src/multimediakit/audio/qaudioinput.h
Normal 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
|
||||
867
src/multimediakit/audio/qaudioinput_alsa_p.cpp
Normal file
867
src/multimediakit/audio/qaudioinput_alsa_p.cpp
Normal file
@@ -0,0 +1,867 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
183
src/multimediakit/audio/qaudioinput_alsa_p.h
Normal file
183
src/multimediakit/audio/qaudioinput_alsa_p.h
Normal 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
|
||||
989
src/multimediakit/audio/qaudioinput_mac_p.cpp
Normal file
989
src/multimediakit/audio/qaudioinput_mac_p.cpp
Normal file
@@ -0,0 +1,989 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
171
src/multimediakit/audio/qaudioinput_mac_p.h
Normal file
171
src/multimediakit/audio/qaudioinput_mac_p.h
Normal 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
|
||||
594
src/multimediakit/audio/qaudioinput_symbian_p.cpp
Normal file
594
src/multimediakit/audio/qaudioinput_symbian_p.cpp
Normal 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"
|
||||
178
src/multimediakit/audio/qaudioinput_symbian_p.h
Normal file
178
src/multimediakit/audio/qaudioinput_symbian_p.h
Normal 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
|
||||
649
src/multimediakit/audio/qaudioinput_win32_p.cpp
Normal file
649
src/multimediakit/audio/qaudioinput_win32_p.cpp
Normal 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"
|
||||
|
||||
171
src/multimediakit/audio/qaudioinput_win32_p.h
Normal file
171
src/multimediakit/audio/qaudioinput_win32_p.h
Normal 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
|
||||
393
src/multimediakit/audio/qaudiooutput.cpp
Normal file
393
src/multimediakit/audio/qaudiooutput.cpp
Normal 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"
|
||||
111
src/multimediakit/audio/qaudiooutput.h
Normal file
111
src/multimediakit/audio/qaudiooutput.h
Normal 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
|
||||
834
src/multimediakit/audio/qaudiooutput_alsa_p.cpp
Normal file
834
src/multimediakit/audio/qaudiooutput_alsa_p.cpp
Normal file
@@ -0,0 +1,834 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
167
src/multimediakit/audio/qaudiooutput_alsa_p.h
Normal file
167
src/multimediakit/audio/qaudiooutput_alsa_p.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
729
src/multimediakit/audio/qaudiooutput_mac_p.cpp
Normal file
729
src/multimediakit/audio/qaudiooutput_mac_p.cpp
Normal 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"
|
||||
171
src/multimediakit/audio/qaudiooutput_mac_p.h
Normal file
171
src/multimediakit/audio/qaudiooutput_mac_p.h
Normal 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
|
||||
713
src/multimediakit/audio/qaudiooutput_symbian_p.cpp
Normal file
713
src/multimediakit/audio/qaudiooutput_symbian_p.cpp
Normal 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"
|
||||
201
src/multimediakit/audio/qaudiooutput_symbian_p.h
Normal file
201
src/multimediakit/audio/qaudiooutput_symbian_p.h
Normal 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
|
||||
715
src/multimediakit/audio/qaudiooutput_win32_p.cpp
Normal file
715
src/multimediakit/audio/qaudiooutput_win32_p.cpp
Normal file
@@ -0,0 +1,715 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
167
src/multimediakit/audio/qaudiooutput_win32_p.h
Normal file
167
src/multimediakit/audio/qaudiooutput_win32_p.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
180
src/multimediakit/audio/qaudiopluginloader.cpp
Normal file
180
src/multimediakit/audio/qaudiopluginloader.cpp
Normal 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
|
||||
|
||||
92
src/multimediakit/audio/qaudiopluginloader_p.h
Normal file
92
src/multimediakit/audio/qaudiopluginloader_p.h
Normal 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
|
||||
423
src/multimediakit/audio/qaudiosystem.cpp
Normal file
423
src/multimediakit/audio/qaudiosystem.cpp
Normal 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"
|
||||
136
src/multimediakit/audio/qaudiosystem.h
Normal file
136
src/multimediakit/audio/qaudiosystem.h
Normal 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
|
||||
143
src/multimediakit/audio/qaudiosystemplugin.cpp
Normal file
143
src/multimediakit/audio/qaudiosystemplugin.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
93
src/multimediakit/audio/qaudiosystemplugin.h
Normal file
93
src/multimediakit/audio/qaudiosystemplugin.h
Normal 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
|
||||
32
src/multimediakit/effects/effects.pri
Normal file
32
src/multimediakit/effects/effects.pri
Normal 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 +=
|
||||
398
src/multimediakit/effects/qsamplecache_p.cpp
Normal file
398
src/multimediakit/effects/qsamplecache_p.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
158
src/multimediakit/effects/qsamplecache_p.h
Normal file
158
src/multimediakit/effects/qsamplecache_p.h
Normal 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
|
||||
301
src/multimediakit/effects/qsoundeffect.cpp
Normal file
301
src/multimediakit/effects/qsoundeffect.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
140
src/multimediakit/effects/qsoundeffect_p.h
Normal file
140
src/multimediakit/effects/qsoundeffect_p.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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
|
||||
955
src/multimediakit/effects/qsoundeffect_pulse_p.cpp
Normal file
955
src/multimediakit/effects/qsoundeffect_pulse_p.cpp
Normal 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"
|
||||
160
src/multimediakit/effects/qsoundeffect_pulse_p.h
Normal file
160
src/multimediakit/effects/qsoundeffect_pulse_p.h
Normal 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
|
||||
233
src/multimediakit/effects/qsoundeffect_qmedia_p.cpp
Normal file
233
src/multimediakit/effects/qsoundeffect_qmedia_p.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
119
src/multimediakit/effects/qsoundeffect_qmedia_p.h
Normal file
119
src/multimediakit/effects/qsoundeffect_qmedia_p.h
Normal 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
|
||||
222
src/multimediakit/effects/qsoundeffect_qsound_p.cpp
Normal file
222
src/multimediakit/effects/qsoundeffect_qsound_p.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
118
src/multimediakit/effects/qsoundeffect_qsound_p.h
Normal file
118
src/multimediakit/effects/qsoundeffect_qsound_p.h
Normal 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
|
||||
232
src/multimediakit/effects/qwavedecoder_p.cpp
Normal file
232
src/multimediakit/effects/qwavedecoder_p.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the Qt 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"
|
||||
134
src/multimediakit/effects/qwavedecoder_p.h
Normal file
134
src/multimediakit/effects/qwavedecoder_p.h
Normal 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
Reference in New Issue
Block a user